Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
+94
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
+144
View File
@@ -0,0 +1,144 @@
// 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 auto 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
+57
View File
@@ -0,0 +1,57 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_BOX_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_BOX_HPP
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategy/area.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
template
<
typename CalculationType = void
>
class cartesian_box
{
public:
template <typename Box>
struct result_type
: strategy::area::detail::result_type
<
Box,
CalculationType
>
{};
template <typename Box>
static inline auto apply(Box const& box)
{
typedef typename result_type<Box>::type return_type;
return return_type(get<max_corner, 0>(box) - get<min_corner, 0>(box))
* return_type(get<max_corner, 1>(box) - get<min_corner, 1>(box));
}
};
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_AREA_BOX_HPP
+120
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
+123
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
+66
View File
@@ -0,0 +1,66 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOXES_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOXES_HPP
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/strategy/cartesian/expand_box.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class cartesian_boxes
{
public:
template <typename Box>
class state
{
friend cartesian_boxes;
Box m_box;
bool m_initialized = false;
};
template <typename Box>
static void apply(state<Box> & st, Box const& box)
{
if (! st.m_initialized)
{
st.m_box = box;
st.m_initialized = true;
}
else
{
strategy::expand::cartesian_box::apply(st.m_box, box);
}
}
template <typename Box>
static void result(state<Box> const& st, Box & box)
{
if (st.m_initialized)
{
box = st.m_box;
}
else
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
}
}
};
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_BOXES_HPP
@@ -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
+111
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
+56
View File
@@ -0,0 +1,56 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_RANGE_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_RANGE_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_point.hpp>
#include <boost/geometry/strategy/cartesian/expand_point.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class cartesian_range
{
public:
template <typename Range, typename Box>
static inline void apply(Range const& range, Box& mbr)
{
auto it = boost::begin(range);
auto const end = boost::end(range);
if (it == end)
{
// initialize box (assign inverse)
geometry::detail::envelope::initialize<Box>::apply(mbr);
return;
}
// initialize box with the first point
envelope::cartesian_point::apply(*it, mbr);
// consider now the remaining points in the range (if any)
for (++it; it != end; ++it)
{
expand::cartesian_point::apply(mbr, *it);
}
}
};
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_ENVELOPE_RANGE_HPP
@@ -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
+69
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
+125
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
+71
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
@@ -0,0 +1,64 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2019 Tinko Bartels, Berlin, Germany.
// Contributed and/or modified by Tinko Bartels,
// as part of Google Summer of Code 2019 program.
// 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_IN_CIRCLE_ROBUST_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP
#include<boost/geometry/util/precise_math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace in_circle
{
/*!
\brief Adaptive precision predicate to check whether a fourth point lies inside the circumcircle of the first three points:
inside (>0), outside (< 0), on the boundary (0).
\ingroup strategies
\tparam CalculationType \tparam_calculation (numeric_limits<ct>::epsilon() and numeric_limits<ct>::digits must be supported for calculation type ct)
\tparam Robustness std::size_t value from 0 (fastest) to 2 (default, most precise).
\details This predicate determines whether a fourth point lies inside the circumcircle of the first three points using an algorithm that is adapted from incircle as described in "Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates" by Jonathan Richard Shewchuk ( https://dl.acm.org/citation.cfm?doid=237218.237337 ). More information and copies of the paper can also be found at https://www.cs.cmu.edu/~quake/robust.html . It is designed to be adaptive in the sense that it should be fast for inputs that lead to correct results with plain float operations but robust for inputs that require higher precision arithmetics.
*/
template <typename CalculationType = double, std::size_t Robustness = 2>
class in_circle_robust
{
public:
template <typename P1, typename P2, typename P3, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P3 const& p3, P const& p)
{
std::array<CalculationType, 2> pa {
{ boost::geometry::get<0>(p1), boost::geometry::get<1>(p1) }};
std::array<CalculationType, 2> pb {
{ boost::geometry::get<0>(p2), boost::geometry::get<1>(p2) }};
std::array<CalculationType, 2> pc {
{ boost::geometry::get<0>(p3), boost::geometry::get<1>(p3) }};
std::array<CalculationType, 2> pd {
{ boost::geometry::get<0>(p), boost::geometry::get<1>(p) }};
CalculationType det =
boost::geometry::detail::precise_math::incircle
<
CalculationType,
Robustness
>(pa, pb, pc, pd);
return det > 0 ? 1
: det < 0 ? -1 : 0;
}
};
} // namespace in_circle
} // namespace strategy
}} // namespace boost::geometry::strategy
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_IN_CIRCLE_ROBUST_HPP
+117
View File
@@ -0,0 +1,117 @@
// Boost.Geometry
// Copyright (c) 2020, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP
#include <boost/mpl/if.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>
#include <boost/geometry/util/precise_math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
/*!
\brief Cartesian area calculation
\ingroup strategies
\details Calculates cartesian area using the trapezoidal rule and precise
summation (useful to increase precision with floating point arithmetic)
\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 precise_cartesian
{
public :
template <typename Geometry>
struct result_type
: strategy::area::detail::result_type
<
Geometry,
CalculationType
>
{};
template <typename Geometry>
class state
{
friend class precise_cartesian;
typedef typename result_type<Geometry>::type return_type;
public:
inline state()
: sum1(0)
, sum2(0)
{
// Strategy supports only 2D areas
assert_dimension<Geometry, 2>();
}
private:
inline return_type area() const
{
return_type const two = 2;
return (sum1 + sum2) / two;
}
return_type sum1;
return_type sum2;
};
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;
auto const det = (return_type(get<0>(p1)) + return_type(get<0>(p2)))
* (return_type(get<1>(p1)) - return_type(get<1>(p2)));
auto const res = boost::geometry::detail::precise_math::two_sum(st.sum1, det);
st.sum1 = res[0];
st.sum2 += res[1];
}
template <typename Geometry>
static inline auto result(state<Geometry>& st)
{
return st.area();
}
};
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_PRECISE_AREA_HPP
+258
View File
@@ -0,0 +1,258 @@
// 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-2023.
// Modifications copyright (c) 2015-2023, 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.
// 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_SIDE_BY_TRIANGLE_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
#include <type_traits>
#include <boost/geometry/core/config.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
#include <boost/geometry/core/access.hpp>
#include <boost/geometry/strategies/cartesian/point_in_point.hpp>
#include <boost/geometry/strategies/compare.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
/*!
\brief Check at which side of a segment a point lies:
left of segment (> 0), right of segment (< 0), on segment (0)
\ingroup strategies
\tparam CalculationType \tparam_calculation
*/
template <typename CalculationType = void>
class side_by_triangle
{
template <typename Policy>
struct eps_policy
{
eps_policy() {}
template <typename Type>
eps_policy(Type const& a, Type const& b, Type const& c, Type const& d)
: policy(a, b, c, d)
{}
Policy policy;
};
struct eps_empty
{
eps_empty() {}
template <typename Type>
eps_empty(Type const&, Type const&, Type const&, Type const&) {}
};
public :
using cs_tag = cartesian_tag;
// Template member function, because it is not always trivial
// or convenient to explicitly mention the typenames in the
// strategy-struct itself.
// Types can be all three different. Therefore it is
// not implemented (anymore) as "segment"
template
<
typename CoordinateType,
typename PromotedType,
typename P1,
typename P2,
typename P,
typename EpsPolicy
>
static inline
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & eps_policy)
{
CoordinateType const x = get<0>(p);
CoordinateType const y = get<1>(p);
CoordinateType const sx1 = get<0>(p1);
CoordinateType const sy1 = get<1>(p1);
CoordinateType const sx2 = get<0>(p2);
CoordinateType const sy2 = get<1>(p2);
PromotedType const dx = sx2 - sx1;
PromotedType const dy = sy2 - sy1;
PromotedType const dpx = x - sx1;
PromotedType const dpy = y - sy1;
eps_policy = EpsPolicy(dx, dy, dpx, dpy);
return geometry::detail::determinant<PromotedType>
(
dx, dy,
dpx, dpy
);
}
template
<
typename CoordinateType,
typename PromotedType,
typename P1,
typename P2,
typename P
>
static inline
PromotedType side_value(P1 const& p1, P2 const& p2, P const& p)
{
eps_empty dummy;
return side_value<CoordinateType, PromotedType>(p1, p2, p, dummy);
}
template
<
typename CoordinateType,
typename PromotedType,
bool AreAllIntegralCoordinates
>
struct compute_side_value
{
template <typename P1, typename P2, typename P, typename EpsPolicy>
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
{
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
}
};
template <typename CoordinateType, typename PromotedType>
struct compute_side_value<CoordinateType, PromotedType, false>
{
template <typename P1, typename P2, typename P, typename EpsPolicy>
static inline PromotedType apply(P1 const& p1, P2 const& p2, P const& p, EpsPolicy & epsp)
{
// For robustness purposes, first check if any two points are
// the same; in this case simply return that the points are
// collinear
if (equals_point_point(p1, p2)
|| equals_point_point(p1, p)
|| equals_point_point(p2, p))
{
return PromotedType(0);
}
// The side_by_triangle strategy computes the signed area of
// the point triplet (p1, p2, p); as such it is (in theory)
// invariant under cyclic permutations of its three arguments.
//
// In the context of numerical errors that arise in
// floating-point computations, and in order to make the strategy
// consistent with respect to cyclic permutations of its three
// arguments, we cyclically permute them so that the first
// argument is always the lexicographically smallest point.
using less = compare::cartesian<compare::less, compare::equals_epsilon>;
if (less::apply(p, p1))
{
if (less::apply(p, p2))
{
// p is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p, p1, p2, epsp);
}
else
{
// p2 is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
}
}
if (less::apply(p1, p2))
{
// p1 is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p1, p2, p, epsp);
}
else
{
// p2 is the lexicographically smallest
return side_value<CoordinateType, PromotedType>(p2, p, p1, epsp);
}
}
};
template <typename P1, typename P2, typename P>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
using coor_t = typename select_calculation_type_alt<CalculationType, P1, P2, P>::type;
// Promote float->double, small int->int
using promoted_t = typename select_most_precise<coor_t, double>::type;
bool const are_all_integral_coordinates =
std::is_integral<typename coordinate_type<P1>::type>::value
&& std::is_integral<typename coordinate_type<P2>::type>::value
&& std::is_integral<typename coordinate_type<P>::type>::value;
eps_policy< math::detail::equals_factor_policy<promoted_t> > epsp;
promoted_t s = compute_side_value
<
coor_t, promoted_t, are_all_integral_coordinates
>::apply(p1, p2, p, epsp);
promoted_t const zero = promoted_t();
return math::detail::equals_by_policy(s, zero, epsp.policy) ? 0
: s > zero ? 1
: -1;
}
private:
template <typename P1, typename P2>
static inline bool equals_point_point(P1 const& p1, P2 const& p2)
{
return strategy::within::cartesian_point_point::apply(p1, p2);
}
};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template <typename CalculationType>
struct default_strategy<cartesian_tag, CalculationType>
{
using type = side_by_triangle<CalculationType>;
};
}
#endif
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_BY_TRIANGLE_HPP
@@ -0,0 +1,99 @@
// Boost.Geometry
// Copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/precise_math.hpp>
#include <boost/geometry/arithmetic/determinant.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
/*!
\brief Predicate to check at which side of a segment a point lies:
left of segment (>0), right of segment (< 0), on segment (0).
\ingroup strategies
\tparam CalculationType \tparam_calculation
\details This predicate determines at which side of a segment a point lies
*/
template
<
typename CalculationType = void
>
struct side_non_robust
{
public:
//! \brief Computes double the signed area of the CCW triangle p1, p2, p
template
<
typename P1,
typename P2,
typename P
>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
typedef typename select_calculation_type_alt
<
CalculationType,
P1,
P2,
P
>::type CoordinateType;
typedef typename select_most_precise
<
CoordinateType,
double
>::type PromotedType;
CoordinateType const x = get<0>(p);
CoordinateType const y = get<1>(p);
CoordinateType const sx1 = get<0>(p1);
CoordinateType const sy1 = get<1>(p1);
CoordinateType const sx2 = get<0>(p2);
CoordinateType const sy2 = get<1>(p2);
//non-robust 1
//the following is 2x slower in some generic cases when compiled with g++
//(tested versions 9 and 10)
//
//auto detleft = (sx1 - x) * (sy2 - y);
//auto detright = (sy1 - y) * (sx2 - x);
//return detleft > detright ? 1 : (detleft < detright ? -1 : 0 );
//non-robust 2
PromotedType const dx = sx2 - sx1;
PromotedType const dy = sy2 - sy1;
PromotedType const dpx = x - sx1;
PromotedType const dpy = y - sy1;
PromotedType sv = geometry::detail::determinant<PromotedType>
(
dx, dy,
dpx, dpy
);
PromotedType const zero = PromotedType();
return sv == zero ? 0 : sv > zero ? 1 : -1;
}
};
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_NON_ROBUST_HPP
+185
View File
@@ -0,0 +1,185 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2019 Tinko Bartels, Berlin, Germany.
// Contributed and/or modified by Tinko Bartels,
// as part of Google Summer of Code 2019 program.
// This file was modified by Oracle on 2021.
// Modifications copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
#define BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
#include <boost/geometry/core/config.hpp>
#include <boost/geometry/strategy/cartesian/side_non_robust.hpp>
#include <boost/geometry/strategies/side.hpp>
#include <boost/geometry/util/select_most_precise.hpp>
#include <boost/geometry/util/select_calculation_type.hpp>
#include <boost/geometry/util/precise_math.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace side
{
struct epsilon_equals_policy
{
public:
template <typename Policy, typename T1, typename T2>
static bool apply(T1 const& a, T2 const& b, Policy const& policy)
{
return boost::geometry::math::detail::equals_by_policy(a, b, policy);
}
};
struct fp_equals_policy
{
public:
template <typename Policy, typename T1, typename T2>
static bool apply(T1 const& a, T2 const& b, Policy const&)
{
return a == b;
}
};
/*!
\brief Adaptive precision predicate to check at which side of a segment a point lies:
left of segment (>0), right of segment (< 0), on segment (0).
\ingroup strategies
\tparam CalculationType \tparam_calculation (numeric_limits<ct>::epsilon() and numeric_limits<ct>::digits must be supported for calculation type ct)
\tparam Robustness std::size_t value from 0 (fastest) to 3 (default, guarantees correct results).
\details This predicate determines at which side of a segment a point lies using an algorithm that is adapted from orient2d as described in "Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates" by Jonathan Richard Shewchuk ( https://dl.acm.org/citation.cfm?doid=237218.237337 ). More information and copies of the paper can also be found at https://www.cs.cmu.edu/~quake/robust.html . It is designed to be adaptive in the sense that it should be fast for inputs that lead to correct results with plain float operations but robust for inputs that require higher precision arithmetics.
*/
template
<
typename CalculationType = void,
typename EqualsPolicy = epsilon_equals_policy,
std::size_t Robustness = 3
>
struct side_robust
{
template <typename CT>
struct epsilon_policy
{
using Policy = boost::geometry::math::detail::equals_factor_policy<CT>;
epsilon_policy() {}
template <typename Type>
epsilon_policy(Type const& a, Type const& b, Type const& c, Type const& d)
: m_policy(a, b, c, d)
{}
Policy m_policy;
public:
template <typename T1, typename T2>
bool apply(T1 a, T2 b) const
{
return EqualsPolicy::apply(a, b, m_policy);
}
};
public:
typedef cartesian_tag cs_tag;
//! \brief Computes the sign of the CCW triangle p1, p2, p
template
<
typename PromotedType,
typename P1,
typename P2,
typename P,
typename EpsPolicyInternal,
std::enable_if_t<std::is_fundamental<PromotedType>::value, int> = 0
>
static inline PromotedType side_value(P1 const& p1,
P2 const& p2,
P const& p,
EpsPolicyInternal& eps_policy)
{
using vec2d = ::boost::geometry::detail::precise_math::vec2d<PromotedType>;
vec2d pa;
pa.x = get<0>(p1);
pa.y = get<1>(p1);
vec2d pb;
pb.x = get<0>(p2);
pb.y = get<1>(p2);
vec2d pc;
pc.x = get<0>(p);
pc.y = get<1>(p);
return ::boost::geometry::detail::precise_math::orient2d
<PromotedType, Robustness>(pa, pb, pc, eps_policy);
}
template
<
typename PromotedType,
typename P1,
typename P2,
typename P,
typename EpsPolicyInternal,
std::enable_if_t<!std::is_fundamental<PromotedType>::value, int> = 0
>
static inline auto side_value(P1 const& p1, P2 const& p2, P const& p,
EpsPolicyInternal&)
{
return side_non_robust<>::apply(p1, p2, p);
}
#ifndef DOXYGEN_SHOULD_SKIP_THIS
template
<
typename P1,
typename P2,
typename P
>
static inline int apply(P1 const& p1, P2 const& p2, P const& p)
{
using coordinate_type = typename select_calculation_type_alt
<
CalculationType,
P1,
P2,
P
>::type;
using promoted_type = typename select_most_precise
<
coordinate_type,
double
>::type;
epsilon_policy<promoted_type> epsp;
promoted_type sv = side_value<promoted_type>(p1, p2, p, epsp);
promoted_type const zero = promoted_type();
return epsp.apply(sv, zero) ? 0
: sv > zero ? 1
: -1;
}
#endif
};
}} // namespace strategy::side
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_CARTESIAN_SIDE_ROBUST_HPP
+44
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
+43
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
+269
View File
@@ -0,0 +1,269 @@
// 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;
// Area formula is implemented for a maximum series order 5
static constexpr auto SeriesOrderNorm = SeriesOrder > 5 ? 5 : SeriesOrder;
//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
calc_t const m_f; // the flattening
calc_t m_coeffs_var[((SeriesOrderNorm+2)*(SeriesOrderNorm+1))/2];
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))
, m_f(formula::flattening<calc_t>(spheroid))
{
typedef geometry::formula::area_formulas
<
calc_t, SeriesOrderNorm, ExpandEpsN
> area_formulas;
calc_t const n = m_f / (calc_t(2) - m_f);
// Generate and evaluate the polynomials on n
// to get the series coefficients (that depend on eps)
area_formulas::evaluate_coeffs_n(n, m_coeffs_var);
}
};
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 const spherical_term = spheroid_const.m_c2 * m_excess_sum;
return_type const ellipsoidal_term = spheroid_const.m_e2
* spheroid_const.m_a2 * m_correction_sum;
// ignore ellipsoidal term if is large (probably from an azimuth
// inaccuracy)
return_type sum = math::abs(ellipsoidal_term/spherical_term) > 0.01
? spherical_term : spherical_term + ellipsoidal_term;
// 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
{
using CT = typename result_type<Geometry>::type;
// if the segment in not on a meridian
if (! geometry::math::equals(get<0>(p1), get<0>(p2)))
{
typedef geometry::formula::area_formulas
<
CT, SeriesOrderNorm, ExpandEpsN
> area_formulas;
// Keep track whenever a segment crosses the prime meridian
if (area_formulas::crosses_prime_meridian(p1, p2))
{
st.m_crosses_prime_meridian++;
}
// if the segment in not on equator
if (! (geometry::math::equals(get<1>(p1), 0)
&& geometry::math::equals(get<1>(p2), 0)))
{
auto 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;
}
}
}
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
+191
View File
@@ -0,0 +1,191 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_AREA_BOX_HPP
#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_AREA_BOX_HPP
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/srs/spheroid.hpp>
#include <boost/geometry/strategies/spherical/get_radius.hpp>
#include <boost/geometry/strategy/area.hpp>
#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
// Based on the approach for spherical coordinate system:
// https://math.stackexchange.com/questions/131735/surface-element-in-spherical-coordinates
// http://www.cs.cmu.edu/afs/cs/academic/class/16823-s16/www/pdfs/appearance-modeling-3.pdf
// https://www.astronomyclub.xyz/celestial-sphere-2/solid-angle-on-the-celestial-sphere.html
// https://mathworld.wolfram.com/SolidAngle.html
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
// and equations for spheroid:
// https://en.wikipedia.org/wiki/Geographic_coordinate_conversion
// https://en.wikipedia.org/wiki/Meridian_arc
// Note that the equations use geodetic latitudes so we do not have to convert them.
// assume(y_max > y_min);
// assume(x_max > x_min);
// M: a*(1-e^2) / (1-e^2*sin(y)^2)^(3/2);
// N: a / sqrt(1-e^2*sin(y)^2);
// O: N*cos(y)*M;
// tellsimp(log(abs(e*sin(y_min)+1)), p_min);
// tellsimp(log(abs(e*sin(y_min)-1)), m_min);
// tellsimp(log(abs(e*sin(y_max)+1)), p_max);
// tellsimp(log(abs(e*sin(y_max)-1)), m_max);
// S: integrate(integrate(O, y, y_min, y_max), x, x_min, x_max);
// combine(S);
//
// An alternative solution to the above formula was suggested by Charles Karney
// https://github.com/boostorg/geometry/pull/832
// The following are formulas for area of a box defined by the equator and some latitude,
// not arbitrary box.
// For e^2 > 0
// dlambda*b^2*sin(phi)/2*(1/(1-e^2*sin(phi)^2) + atanh(e*sin(phi))/(e*sin(phi)))
// For e^2 < 0
// dlambda*b^2*sin(phi)/2*(1/(1-e^2*sin(phi)^2) + atan(ea*sin(phi))/(ea*sin(phi)))
// where ea = sqrt(-e^2)
template
<
typename Spheroid = srs::spheroid<double>,
typename CalculationType = void
>
class geographic_box
{
public:
template <typename Box>
struct result_type
: strategy::area::detail::result_type
<
Box,
CalculationType
>
{};
geographic_box() = default;
explicit geographic_box(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Box>
inline auto apply(Box const& box) const
{
typedef typename result_type<Box>::type return_type;
return_type const c0 = 0;
return_type x_min = get_as_radian<min_corner, 0>(box); // lon
return_type y_min = get_as_radian<min_corner, 1>(box); // lat
return_type x_max = get_as_radian<max_corner, 0>(box);
return_type y_max = get_as_radian<max_corner, 1>(box);
math::normalize_spheroidal_box_coordinates<radian>(x_min, y_min, x_max, y_max);
if (x_min == x_max || y_max == y_min)
{
return c0;
}
return_type const e2 = formula::eccentricity_sqr<return_type>(m_spheroid);
return_type const x_diff = x_max - x_min;
return_type const sin_y_min = sin(y_min);
return_type const sin_y_max = sin(y_max);
if (math::equals(e2, c0))
{
// spherical formula
return_type const a = get_radius<0>(m_spheroid);
return x_diff * (sin_y_max - sin_y_min) * a * a;
}
return_type const c1 = 1;
return_type const c2 = 2;
return_type const b = get_radius<2>(m_spheroid);
/*
return_type const c4 = 4;
return_type const e = math::sqrt(e2);
return_type const p_min = log(math::abs(e * sin_y_min + c1));
return_type const p_max = log(math::abs(e * sin_y_max + c1));
return_type const m_min = log(math::abs(e * sin_y_min - c1));
return_type const m_max = log(math::abs(e * sin_y_max - c1));
return_type const n_min = e * sin_y_min * sin_y_min;
return_type const n_max = e * sin_y_max * sin_y_max;
return_type const d_min = e * n_min - c1;
return_type const d_max = e * n_max - c1;
// NOTE: For equal latitudes the original formula generated by maxima may give negative
// result. It's caused by the order of operations, so here they're rearranged for
// symmetry.
return_type const comp0 = (p_min - m_min) / (c4 * e * d_min);
return_type const comp1 = sin_y_min / (c2 * d_min);
return_type const comp2 = n_min * (m_min - p_min) / (c4 * d_min);
return_type const comp3 = (p_max - m_max) / (c4 * e * d_max);
return_type const comp4 = sin_y_max / (c2 * d_max);
return_type const comp5 = n_max * (m_max - p_max) / (c4 * d_max);
return_type const comp02 = comp0 + comp1 + comp2;
return_type const comp35 = comp3 + comp4 + comp5;
return b * b * x_diff * (comp02 - comp35);
*/
return_type const comp0_min = c1 / (c1 - e2 * sin_y_min * sin_y_min);
return_type const comp0_max = c1 / (c1 - e2 * sin_y_max * sin_y_max);
// NOTE: For latitudes equal to 0 the original formula returns NAN
return_type comp1_min = 0, comp1_max = 0;
if (e2 > c0)
{
return_type const e = math::sqrt(e2);
return_type const e_sin_y_min = e * sin_y_min;
return_type const e_sin_y_max = e * sin_y_max;
comp1_min = e_sin_y_min == c0 ? c1 : atanh(e_sin_y_min) / e_sin_y_min;
comp1_max = e_sin_y_max == c0 ? c1 : atanh(e_sin_y_max) / e_sin_y_max;
}
else
{
return_type const ea = math::sqrt(-e2);
return_type const ea_sin_y_min = ea * sin_y_min;
return_type const ea_sin_y_max = ea * sin_y_max;
comp1_min = ea_sin_y_min == c0 ? c1 : atan(ea_sin_y_min) / ea_sin_y_min;
comp1_max = ea_sin_y_max == c0 ? c1 : atan(ea_sin_y_max) / ea_sin_y_max;
}
return_type const comp01_min = sin_y_min * (comp0_min + comp1_min);
return_type const comp01_max = sin_y_max * (comp0_max + comp1_max);
return b * b * x_diff * (comp01_max - comp01_min) / c2;
}
Spheroid model() const
{
return m_spheroid;
}
private:
Spheroid m_spheroid;
};
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_AREA_BOX_HPP
+94
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
+118
View File
@@ -0,0 +1,118 @@
// Boost.Geometry
// Copyright (c) 2021-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_RANGE_HPP
#define BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_RANGE_HPP
#include <boost/geometry/strategy/geographic/envelope_segment.hpp>
#include <boost/geometry/strategy/geographic/expand_segment.hpp>
#include <boost/geometry/strategy/spherical/envelope_range.hpp>
// Get rid of this dependency?
#include <boost/geometry/strategies/spherical/point_in_poly_winding.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_linestring
{
public:
using model_type = Spheroid;
geographic_linestring()
: m_spheroid()
{}
explicit geographic_linestring(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Range, typename Box>
void apply(Range const& range, Box& mbr) const
{
auto const envelope_s = envelope::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(m_spheroid);
auto const expand_s = expand::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(m_spheroid);
detail::spheroidal_linestring(range, mbr, envelope_s, expand_s);
}
Spheroid model() const
{
return m_spheroid;
}
private:
Spheroid m_spheroid;
};
template
<
typename FormulaPolicy = strategy::andoyer,
typename Spheroid = geometry::srs::spheroid<double>,
typename CalculationType = void
>
class geographic_ring
{
public:
using model_type = Spheroid;
geographic_ring()
: m_spheroid()
{}
explicit geographic_ring(Spheroid const& spheroid)
: m_spheroid(spheroid)
{}
template <typename Range, typename Box>
void apply(Range const& range, Box& mbr) const
{
auto const envelope_s = envelope::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(m_spheroid);
auto const expand_s = expand::geographic_segment
<
FormulaPolicy, Spheroid, CalculationType
>(m_spheroid);
auto const within_s = within::detail::spherical_winding_base
<
envelope::detail::side_of_pole<CalculationType>, CalculationType
>();
detail::spheroidal_ring(range, mbr, envelope_s, expand_s, within_s);
}
Spheroid model() const
{
return m_spheroid;
}
private:
Spheroid m_spheroid;
};
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_GEOGRAPHIC_ENVELOPE_RANGE_HPP
@@ -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
+107
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
+175
View File
@@ -0,0 +1,175 @@
// Boost.Geometry
// Copyright (c) 2017-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_RELATE_HPP
#define BOOST_GEOMETRY_STRATEGY_RELATE_HPP
#include <type_traits>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/core/point_type.hpp>
#include <boost/geometry/core/static_assert.hpp>
#include <boost/geometry/core/topological_dimension.hpp>
#include <boost/geometry/strategies/covered_by.hpp>
#include <boost/geometry/strategies/intersection.hpp>
#include <boost/geometry/strategies/within.hpp>
namespace boost { namespace geometry
{
namespace strategy
{
namespace point_in_geometry
{
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
<
typename Point,
typename Geometry,
typename Tag1 = typename tag<Point>::type,
typename Tag2 = typename tag<Geometry>::type
>
struct default_strategy
: strategy::within::services::default_strategy
<
Point,
Geometry
>
{
typedef typename default_strategy::type within_strategy_type;
typedef typename strategy::covered_by::services::default_strategy
<
Point,
Geometry
>::type covered_by_strategy_type;
static const bool same_strategies = std::is_same<within_strategy_type, covered_by_strategy_type>::value;
BOOST_GEOMETRY_STATIC_ASSERT(same_strategies,
"Default within and covered_by strategies not compatible.",
within_strategy_type, covered_by_strategy_type);
};
template<typename Point, typename Geometry>
struct default_strategy<Point, Geometry, point_tag, point_tag>
: strategy::within::services::default_strategy<Point, Geometry>
{};
template<typename Point, typename Geometry>
struct default_strategy<Point, Geometry, point_tag, multi_point_tag>
: strategy::within::services::default_strategy<Point, Geometry>
{};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
} // namespace point_in_geometry
namespace relate
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Geometry>
struct default_intersection_strategy
: strategy::intersection::services::default_strategy
<
typename cs_tag<Geometry>::type
>
{};
template <typename PointLike, typename Geometry>
struct default_point_in_geometry_strategy
: point_in_geometry::services::default_strategy
<
typename point_type<PointLike>::type,
Geometry
>
{};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
template
<
typename Geometry1,
typename Geometry2,
int TopDim1 = geometry::topological_dimension<Geometry1>::value,
int TopDim2 = geometry::topological_dimension<Geometry2>::value
>
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
"Not implemented for these types.",
Geometry1, Geometry2);
};
template <typename PointLike1, typename PointLike2>
struct default_strategy<PointLike1, PointLike2, 0, 0>
: detail::default_point_in_geometry_strategy<PointLike1, PointLike2>
{};
template <typename PointLike, typename Geometry, int TopDim2>
struct default_strategy<PointLike, Geometry, 0, TopDim2>
: detail::default_point_in_geometry_strategy<PointLike, Geometry>
{};
template <typename Geometry, typename PointLike, int TopDim1>
struct default_strategy<Geometry, PointLike, TopDim1, 0>
: detail::default_point_in_geometry_strategy<PointLike, Geometry>
{};
template <typename Geometry1, typename Geometry2>
struct default_strategy<Geometry1, Geometry2, 1, 1>
: detail::default_intersection_strategy<Geometry1>
{};
template <typename Geometry1, typename Geometry2>
struct default_strategy<Geometry1, Geometry2, 1, 2>
: detail::default_intersection_strategy<Geometry1>
{};
template <typename Geometry1, typename Geometry2>
struct default_strategy<Geometry1, Geometry2, 2, 1>
: detail::default_intersection_strategy<Geometry1>
{};
template <typename Geometry1, typename Geometry2>
struct default_strategy<Geometry1, Geometry2, 2, 2>
: detail::default_intersection_strategy<Geometry1>
{};
} // namespace services
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
} // namespace relate
} // namespace strategy
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_RELATE_HPP
+202
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
+115
View File
@@ -0,0 +1,115 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_BOX_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_BOX_HPP
#include <boost/geometry/core/coordinate_type.hpp>
#include <boost/geometry/core/coordinate_dimension.hpp>
#include <boost/geometry/core/radian_access.hpp>
#include <boost/geometry/srs/sphere.hpp>
#include <boost/geometry/strategies/spherical/get_radius.hpp>
#include <boost/geometry/strategy/area.hpp>
#include <boost/geometry/util/normalize_spheroidal_box_coordinates.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace area
{
// https://math.stackexchange.com/questions/131735/surface-element-in-spherical-coordinates
// http://www.cs.cmu.edu/afs/cs/academic/class/16823-s16/www/pdfs/appearance-modeling-3.pdf
// https://www.astronomyclub.xyz/celestial-sphere-2/solid-angle-on-the-celestial-sphere.html
// https://mathworld.wolfram.com/SolidAngle.html
// https://en.wikipedia.org/wiki/Spherical_coordinate_system
// Note that the equations used in the above articles are spherical polar coordinates.
// We use spherical equatorial, so the equation is different:
// assume(y_max > y_min);
// assume(x_max > x_min);
// /* because of polar to equatorial conversion */
// sin(%pi / 2 - y);
// O: r ^ 2 * cos(y);
// S: integrate(integrate(O, y, y_min, y_max), x, x_min, x_max);
template
<
typename RadiusTypeOrSphere = double,
typename CalculationType = void
>
class spherical_box
{
typedef typename strategy_detail::get_radius
<
RadiusTypeOrSphere
>::type radius_type;
public:
template <typename Box>
struct result_type
: strategy::area::detail::result_type
<
Box,
CalculationType
>
{};
// For consistency with other strategies the radius is set to 1
inline spherical_box()
: m_radius(1.0)
{}
template <typename RadiusOrSphere>
explicit inline spherical_box(RadiusOrSphere const& radius_or_sphere)
: m_radius(strategy_detail::get_radius
<
RadiusOrSphere
>::apply(radius_or_sphere))
{}
template <typename Box>
inline auto apply(Box const& box) const
{
typedef typename result_type<Box>::type return_type;
return_type x_min = get_as_radian<min_corner, 0>(box); // lon
return_type y_min = get_as_radian<min_corner, 1>(box); // lat
return_type x_max = get_as_radian<max_corner, 0>(box);
return_type y_max = get_as_radian<max_corner, 1>(box);
if (x_min == x_max || y_max == y_min)
{
return return_type(0);
}
math::normalize_spheroidal_box_coordinates<radian>(x_min, y_min, x_max, y_max);
return (x_max - x_min)
* (sin(y_max) - sin(y_min))
* return_type(m_radius * m_radius);
}
srs::sphere<radius_type> model() const
{
return srs::sphere<radius_type>(m_radius);
}
private:
radius_type m_radius;
};
}} // namespace strategy::area
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_AREA_BOX_HPP
+113
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
+75
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
+59
View File
@@ -0,0 +1,59 @@
// Boost.Geometry
// Copyright (c) 2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOXES_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOXES_HPP
#include <vector>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
class spherical_boxes
{
public:
template <typename Box>
class state
{
friend spherical_boxes;
std::vector<Box> m_boxes;
};
template <typename Box>
static void apply(state<Box> & st, Box const& box)
{
st.m_boxes.push_back(box);
}
template <typename Box>
static void result(state<Box> const& st, Box & box)
{
if (! st.m_boxes.empty())
{
geometry::detail::envelope::envelope_range_of_boxes::apply(st.m_boxes, box);
}
else
{
geometry::detail::envelope::initialize<Box, 0, dimension<Box>::value>::apply(box);
}
}
};
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_BOXES_HPP
@@ -0,0 +1,351 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
// Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
// Copyright (c) 2015-2023, 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 <algorithm>
#include <cstddef>
#include <utility>
#include <vector>
#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/strategy/cartesian/expand_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)
{
// 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 (auto it = boost::begin(multipoint); it != boost::end(multipoint); ++it)
{
typename boost::range_value<MultiPoint>::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)
{
auto it1 = boost::begin(sorted_range);
auto 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)
{
// compute min and max longitude values
auto const min_max_longitudes
= std::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
{
auto const min_max_latitudes = std::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 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
auto 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
+111
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
+280
View File
@@ -0,0 +1,280 @@
// Boost.Geometry
// Copyright (c) 2021-2022, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Licensed under the Boost Software License version 1.0.
// http://www.boost.org/users/license.html
#ifndef BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_RANGE_HPP
#define BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_RANGE_HPP
#include <boost/range/size.hpp>
#include <boost/geometry/algorithms/assign.hpp>
#include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/strategy/spherical/envelope_point.hpp>
#include <boost/geometry/strategy/spherical/envelope_segment.hpp>
#include <boost/geometry/strategy/spherical/expand_segment.hpp>
#include <boost/geometry/views/closeable_view.hpp>
// Get rid of this dependency?
#include <boost/geometry/strategies/spherical/point_in_poly_winding.hpp>
namespace boost { namespace geometry
{
namespace strategy { namespace envelope
{
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template <typename Range, typename Box, typename EnvelopeStrategy, typename ExpandStrategy>
inline void spheroidal_linestring(Range const& range, Box& mbr,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy)
{
auto it = boost::begin(range);
auto const end = boost::end(range);
if (it == end)
{
// initialize box (assign inverse)
geometry::detail::envelope::initialize<Box>::apply(mbr);
return;
}
auto prev = it;
++it;
if (it == end)
{
// initialize box with the first point
envelope::spherical_point::apply(*prev, mbr);
return;
}
// initialize box with the first segment
envelope_strategy.apply(*prev, *it, mbr);
// consider now the remaining segments in the range (if any)
prev = it;
++it;
while (it != end)
{
using point_t = typename boost::range_value<Range>::type;
geometry::model::referring_segment<point_t const> const seg(*prev, *it);
expand_strategy.apply(mbr, seg);
prev = it;
++it;
}
}
// This strategy is intended to be used together with winding strategy to check
// if ring/polygon has a pole in its interior or exterior. It is not intended
// for checking if the pole is on the boundary.
template <typename CalculationType = void>
struct side_of_pole
{
typedef spherical_tag cs_tag;
template <typename P>
static inline int apply(P const& p1, P const& p2, P const& pole)
{
using calc_t = typename promote_floating_point
<
typename select_calculation_type_alt
<
CalculationType, P
>::type
>::type;
using units_t = typename geometry::detail::cs_angular_units<P>::type;
using constants = math::detail::constants_on_spheroid<calc_t, units_t>;
calc_t const c0 = 0;
calc_t const pi = constants::half_period();
calc_t const lon1 = get<0>(p1);
calc_t const lat1 = get<1>(p1);
calc_t const lon2 = get<0>(p2);
calc_t const lat2 = get<1>(p2);
calc_t const lat_pole = get<1>(pole);
calc_t const s_lon_diff = math::longitude_distance_signed<units_t>(lon1, lon2);
bool const s_vertical = math::equals(s_lon_diff, c0)
|| math::equals(s_lon_diff, pi);
// Side of vertical segment is 0 for both poles.
if (s_vertical)
{
return 0;
}
// This strategy shouldn't be called in this case but just in case
// check if segment starts at a pole
if (math::equals(lat_pole, lat1) || math::equals(lat_pole, lat2))
{
return 0;
}
// -1 is rhs
// 1 is lhs
if (lat_pole >= c0) // north pole
{
return s_lon_diff < c0 ? -1 : 1;
}
else // south pole
{
return s_lon_diff > c0 ? -1 : 1;
}
}
};
template <typename Point, typename Range, typename Strategy>
inline int point_in_range(Point const& point, Range const& range, Strategy const& strategy)
{
typename Strategy::state_type state;
auto it = boost::begin(range);
auto const end = boost::end(range);
for (auto previous = it++ ; it != end ; ++previous, ++it )
{
if (! strategy.apply(point, *previous, *it, state))
{
break;
}
}
return strategy.result(state);
}
template <typename T, typename Ring, typename PoleWithinStrategy>
inline bool pole_within(T const& lat_pole, Ring const& ring,
PoleWithinStrategy const& pole_within_strategy)
{
if (boost::size(ring) < core_detail::closure::minimum_ring_size
<
geometry::closure<Ring>::value
>::value)
{
return false;
}
using point_t = typename geometry::point_type<Ring>::type;
point_t point;
geometry::assign_zero(point);
geometry::set<1>(point, lat_pole);
geometry::detail::closed_clockwise_view<Ring const> view(ring);
return point_in_range(point, view, pole_within_strategy) > 0;
}
template
<
typename Range,
typename Box,
typename EnvelopeStrategy,
typename ExpandStrategy,
typename PoleWithinStrategy
>
inline void spheroidal_ring(Range const& range, Box& mbr,
EnvelopeStrategy const& envelope_strategy,
ExpandStrategy const& expand_strategy,
PoleWithinStrategy const& pole_within_strategy)
{
geometry::detail::closed_view<Range const> closed_range(range);
spheroidal_linestring(closed_range, mbr, envelope_strategy, expand_strategy);
using coord_t = typename geometry::coordinate_type<Box>::type;
using point_t = typename geometry::point_type<Box>::type;
using units_t = typename geometry::detail::cs_angular_units<point_t>::type;
using constants_t = math::detail::constants_on_spheroid<coord_t, units_t>;
coord_t const two_pi = constants_t::period();
coord_t const lon_min = geometry::get<0, 0>(mbr);
coord_t const lon_max = geometry::get<1, 0>(mbr);
// If box covers the whole longitude range it is possible that the ring contains
// one of the poles.
// Technically it is possible that a reversed ring may cover more than
// half of the globe and mbr of it's linear ring may be small and not cover the
// longitude range. We currently don't support such rings.
if (lon_max - lon_min >= two_pi)
{
coord_t const lat_n_pole = constants_t::max_latitude();
coord_t const lat_s_pole = constants_t::min_latitude();
coord_t lat_min = geometry::get<0, 1>(mbr);
coord_t lat_max = geometry::get<1, 1>(mbr);
// Normalize box latitudes, just in case
if (math::equals(lat_min, lat_s_pole))
{
lat_min = lat_s_pole;
}
if (math::equals(lat_max, lat_n_pole))
{
lat_max = lat_n_pole;
}
if (lat_max < lat_n_pole)
{
if (pole_within(lat_n_pole, range, pole_within_strategy))
{
lat_max = lat_n_pole;
}
}
if (lat_min > lat_s_pole)
{
if (pole_within(lat_s_pole, range, pole_within_strategy))
{
lat_min = lat_s_pole;
}
}
geometry::set<0, 1>(mbr, lat_min);
geometry::set<1, 1>(mbr, lat_max);
}
}
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename CalculationType = void>
class spherical_linestring
{
public:
template <typename Range, typename Box>
static inline void apply(Range const& range, Box& mbr)
{
detail::spheroidal_linestring(range, mbr,
envelope::spherical_segment<CalculationType>(),
expand::spherical_segment<CalculationType>());
}
};
template <typename CalculationType = void>
class spherical_ring
{
public:
template <typename Range, typename Box>
static inline void apply(Range const& range, Box& mbr)
{
detail::spheroidal_ring(range, mbr,
envelope::spherical_segment<CalculationType>(),
expand::spherical_segment<CalculationType>(),
within::detail::spherical_winding_base
<
envelope::detail::side_of_pole<CalculationType>,
CalculationType
>());
}
};
}} // namespace strategy::envelope
}} //namepsace boost::geometry
#endif // BOOST_GEOMETRY_STRATEGY_SPHERICAL_ENVELOPE_RANGE_HPP
+430
View File
@@ -0,0 +1,430 @@
// 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
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 (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
+175
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
+231
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
+113
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