diff --git a/doc/doxy/doxygen_input/groups/groups.hpp b/doc/doxy/doxygen_input/groups/groups.hpp
index 1caf7cf63..d2659b561 100644
--- a/doc/doxy/doxygen_input/groups/groups.hpp
+++ b/doc/doxy/doxygen_input/groups/groups.hpp
@@ -2,8 +2,8 @@
//
// Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands.
-// This file was modified by Oracle on 2018.
-// Modifications copyright (c) 2018, Oracle and/or its affiliates.
+// This file was modified by Oracle on 2018-2021.
+// Modifications copyright (c) 2018-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
@@ -20,6 +20,7 @@
\defgroup area area: calculate area of a Geometry
\defgroup arithmetic arithmetic: arithmetic operations on points
\defgroup assign assign: assign values to geometries
+\defgroup azimuth azimuth: calculate azimuth of a segment defined by a pair of points
\defgroup buffer buffer: calculate buffer of a geometry
\defgroup centroid centroid: calculate centroid (center of gravity) of a geometry
\defgroup clear clear: clear geometries
diff --git a/doc/imports.qbk b/doc/imports.qbk
index a184f1513..a5fdacf08 100644
--- a/doc/imports.qbk
+++ b/doc/imports.qbk
@@ -5,7 +5,7 @@
Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
Copyright (c) 2009-2012 Bruno Lalande, Paris, France.
- Copyright (c) 2018, Oracle and/or its affiliates.
+ Copyright (c) 2018-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
@@ -24,6 +24,8 @@
[import src/examples/algorithms/assign_3d_point.cpp]
[import src/examples/algorithms/assign_inverse.cpp]
[import src/examples/algorithms/assign_points.cpp]
+[import src/examples/algorithms/azimuth.cpp]
+[import src/examples/algorithms/azimuth_strategy.cpp]
[import src/examples/algorithms/buffer_with_strategies.cpp]
[import src/examples/algorithms/clear.cpp]
[import src/examples/algorithms/centroid.cpp]
diff --git a/doc/make_qbk.py b/doc/make_qbk.py
index 8a5cb6100..f4d7881e3 100755
--- a/doc/make_qbk.py
+++ b/doc/make_qbk.py
@@ -6,7 +6,7 @@
# Copyright (c) 2009-2012 Mateusz Loskot (mateusz@loskot.net), London, UK
# Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland
#
-# Copyright (c) 2018, Oracle and/or its affiliates.
+# Copyright (c) 2018-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,
@@ -96,7 +96,7 @@ def cs_to_quickbook(section):
call_doxygen()
algorithms = ["append", "assign", "make", "clear"
- , "area", "buffer", "centroid", "convert", "correct", "covered_by"
+ , "area", "azimuth", "buffer", "centroid", "convert", "correct", "covered_by"
, "convex_hull", "crosses", "densify", "difference"
, "discrete_frechet_distance", "discrete_hausdorff_distance", "disjoint"
, "distance", "envelope", "equals", "expand", "for_each", "is_empty"
diff --git a/doc/quickref.xml b/doc/quickref.xml
index bad6b5097..092a7f2ae 100644
--- a/doc/quickref.xml
+++ b/doc/quickref.xml
@@ -364,6 +364,10 @@
coordinate values)
+ Azimuth
+
+ azimuth
+
Buffer
buffer
diff --git a/doc/reference.qbk b/doc/reference.qbk
index aa0be56c0..a9270a5fb 100644
--- a/doc/reference.qbk
+++ b/doc/reference.qbk
@@ -6,8 +6,8 @@
Copyright (c) 2009-2017 Bruno Lalande, Paris, France.
Copyright (c) 2013-2017 Adam Wulkiewicz, Lodz, Poland.
- This file was modified by Oracle on 2014, 2017, 2018.
- Modifications copyright (c) 2014-2018, Oracle and/or its affiliates.
+ This file was modified by Oracle on 2014-2021.
+ Modifications copyright (c) 2014-2021, 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
@@ -80,6 +80,10 @@
[include generated/append.qbk]
+[section:azimuth azimuth]
+[include generated/azimuth.qbk]
+[endsect]
+
[section:buffer buffer]
[include generated/buffer.qbk]
[endsect]
diff --git a/doc/reference/algorithms/azimuth.qbk b/doc/reference/algorithms/azimuth.qbk
new file mode 100644
index 000000000..5b2606661
--- /dev/null
+++ b/doc/reference/algorithms/azimuth.qbk
@@ -0,0 +1,22 @@
+[/============================================================================
+ Boost.Geometry
+
+ Copyright (c) 2021, 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)
+=============================================================================/]
+
+[def __this_function__ azimuth]
+
+[heading_conformance_no_ogc __this_function__]
+[note PostGIS contains an algorithm ST_Azimuth with the same functionality.
+ See the [@https://postgis.net/docs/ST_Azimuth.html PostGIS documentation].
+]
+
+[heading Behavior]
+The algorithm calculates the azimuth of a segment defined by a pair of points.
+
+[note The result is in radians.]
diff --git a/doc/src/examples/algorithms/azimuth.cpp b/doc/src/examples/algorithms/azimuth.cpp
new file mode 100644
index 000000000..0f799920a
--- /dev/null
+++ b/doc/src/examples/algorithms/azimuth.cpp
@@ -0,0 +1,42 @@
+// Boost.Geometry
+// QuickBook Example
+
+// Copyright (c) 2021, 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)
+
+//[azimuth
+//` Shows how to calculate azimuth
+
+#include
+
+#include
+#include
+
+int main()
+{
+ typedef boost::geometry::model::d2::point_xy point_type;
+
+ point_type p1(0, 0);
+ point_type p2(1, 1);
+
+ auto azimuth = boost::geometry::azimuth(p1, p2);
+
+ std::cout << "azimuth: " << azimuth << std::endl;
+
+ return 0;
+}
+
+//]
+
+//[azimuth_output
+/*`
+Output:
+[pre
+azimuth: 0.785398
+]
+*/
+//]
diff --git a/doc/src/examples/algorithms/azimuth_strategy.cpp b/doc/src/examples/algorithms/azimuth_strategy.cpp
new file mode 100644
index 000000000..2a8ef5178
--- /dev/null
+++ b/doc/src/examples/algorithms/azimuth_strategy.cpp
@@ -0,0 +1,46 @@
+// Boost.Geometry
+// QuickBook Example
+
+// Copyright (c) 2021, 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)
+
+//[azimuth_strategy
+//` Shows how to calculate azimuth in geographic coordinate system
+
+#include
+
+#include
+#include
+
+int main()
+{
+ namespace bg = boost::geometry;
+ typedef bg::model::point > point_type;
+
+ point_type p1(0, 0);
+ point_type p2(1, 1);
+
+ bg::srs::spheroid spheroid(6378137.0, 6356752.3142451793);
+ bg::strategies::azimuth::geographic<> strategy(spheroid);
+
+ auto azimuth = boost::geometry::azimuth(p1, p2, strategy);
+
+ std::cout << "azimuth: " << azimuth << std::endl;
+
+ return 0;
+}
+
+//]
+
+//[azimuth_strategy_output
+/*`
+Output:
+[pre
+azimuth: 0.788674
+]
+*/
+//]
diff --git a/include/boost/geometry/algorithms/azimuth.hpp b/include/boost/geometry/algorithms/azimuth.hpp
new file mode 100644
index 000000000..2e97eed2f
--- /dev/null
+++ b/include/boost/geometry/algorithms/azimuth.hpp
@@ -0,0 +1,226 @@
+// Boost.Geometry
+
+// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
+
+// This file was modified by Oracle on 2014-2021.
+// Modifications copyright (c) 2014-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_ALGORITHMS_AZIMUTH_HPP
+#define BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP
+
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+
+namespace boost { namespace geometry
+{
+
+
+#ifndef DOXYGEN_NO_DETAIL
+namespace detail
+{
+
+} // namespace detail
+#endif // DOXYGEN_NO_DETAIL
+
+
+#ifndef DOXYGEN_NO_DISPATCH
+namespace dispatch
+{
+
+template
+<
+ typename Geometry1, typename Geometry2,
+ typename Tag1 = typename tag::type,
+ typename Tag2 = typename tag::type
+>
+struct azimuth : not_implemented
+{};
+
+template
+struct azimuth
+{
+ template
+ static auto apply(Point1 const& p1, Point2 const& p2, Strategy const& strategy)
+ {
+ typedef typename decltype(strategy.azimuth())::template result_type
+ <
+ typename coordinate_type::type,
+ typename coordinate_type::type
+ >::type calc_t;
+
+ calc_t result = 0;
+ calc_t const x1 = geometry::get_as_radian<0>(p1);
+ calc_t const y1 = geometry::get_as_radian<1>(p1);
+ calc_t const x2 = geometry::get_as_radian<0>(p2);
+ calc_t const y2 = geometry::get_as_radian<1>(p2);
+
+ strategy.azimuth().apply(x1, y1, x2, y2, result);
+
+ // NOTE: It is not clear which units we should use for the result.
+ // For now radians are always returned but a user could expect
+ // e.g. something like this:
+ /*
+ bool const both_degree = std::is_same
+ <
+ typename detail::cs_angular_units::type,
+ geometry::degree
+ >::value
+ && std::is_same
+ <
+ typename detail::cs_angular_units::type,
+ geometry::degree
+ >::value;
+ if (both_degree)
+ {
+ result *= math::r2d();
+ }
+ */
+
+ return result;
+ }
+};
+
+} // namespace dispatch
+#endif // DOXYGEN_NO_DISPATCH
+
+
+namespace resolve_strategy
+{
+
+template
+<
+ typename Strategy,
+ bool IsUmbrella = strategies::detail::is_umbrella_strategy::value
+>
+struct azimuth
+{
+ template
+ static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
+ {
+ return dispatch::azimuth::apply(p1, p2, strategy);
+ }
+};
+
+template
+struct azimuth
+{
+ template
+ static auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
+ {
+ using strategies::azimuth::services::strategy_converter;
+ return dispatch::azimuth
+ <
+ P1, P2
+ >::apply(p1, p2, strategy_converter::get(strategy));
+ }
+};
+
+template <>
+struct azimuth
+{
+ template
+ static auto apply(P1 const& p1, P2 const& p2, default_strategy)
+ {
+ typedef typename strategies::azimuth::services::default_strategy
+ <
+ P1, P2
+ >::type strategy_type;
+
+ return dispatch::azimuth::apply(p1, p2, strategy_type());
+ }
+};
+
+
+} // namespace resolve_strategy
+
+
+namespace resolve_variant
+{
+} // namespace resolve_variant
+
+
+/*!
+\brief Calculate azimuth of a segment defined by a pair of points.
+\ingroup azimuth
+\tparam Point1 Type of the first point of a segment.
+\tparam Point2 Type of the second point of a segment.
+\param point1 First point of a segment.
+\param point2 Second point of a segment.
+\return Azimuth in radians.
+
+\qbk{[include reference/algorithms/azimuth.qbk]}
+
+\qbk{
+[heading Example]
+[azimuth]
+[azimuth_output]
+}
+*/
+template
+inline auto azimuth(Point1 const& point1, Point2 const& point2)
+{
+ concepts::check();
+ concepts::check();
+
+ return resolve_strategy::azimuth
+ <
+ default_strategy
+ >::apply(point1, point2, default_strategy());
+}
+
+
+/*!
+\brief Calculate azimuth of a segment defined by a pair of points.
+\ingroup azimuth
+\tparam Point1 Type of the first point of a segment.
+\tparam Point2 Type of the second point of a segment.
+\tparam Strategy Type of an umbrella strategy defining azimuth strategy.
+\param point1 First point of a segment.
+\param point2 Second point of a segment.
+\param strategy Umbrella strategy defining azimuth strategy.
+\return Azimuth in radians.
+
+\qbk{distinguish,with strategy}
+\qbk{[include reference/algorithms/azimuth.qbk]}
+
+\qbk{
+[heading Example]
+[azimuth_strategy]
+[azimuth_strategy_output]
+}
+*/
+template
+inline auto azimuth(Point1 const& point1, Point2 const& point2, Strategy const& strategy)
+{
+ concepts::check();
+ concepts::check();
+
+ return resolve_strategy::azimuth::apply(point1, point2, strategy);
+}
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_ALGORITHMS_AZIMUTH_HPP
diff --git a/include/boost/geometry/algorithms/detail/azimuth.hpp b/include/boost/geometry/algorithms/detail/azimuth.hpp
deleted file mode 100644
index 21007778b..000000000
--- a/include/boost/geometry/algorithms/detail/azimuth.hpp
+++ /dev/null
@@ -1,152 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2014, 2016, 2017.
-// Modifications copyright (c) 2014-2017, 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_ALGORITHMS_DETAIL_AZIMUTH_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
-
-
-#include
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include
-
-#include
-
-
-namespace boost { namespace geometry
-{
-
-// An azimuth is an angle between a vector/segment from origin to a point of
-// interest and a reference vector. Typically north-based azimuth is used.
-// North direction is used as a reference, angle is measured clockwise
-// (North - 0deg, East - 90deg). For consistency in 2d cartesian CS
-// the reference vector is Y axis, angle is measured clockwise.
-// http://en.wikipedia.org/wiki/Azimuth
-
-#ifndef DOXYGEN_NO_DISPATCH
-namespace detail_dispatch
-{
-
-template
-struct azimuth
- : not_implemented
-{};
-
-template
-struct azimuth
-{
- template
- static inline ReturnType apply(P1 const& p1, P2 const& p2, Spheroid const& spheroid)
- {
- return geometry::formula::vincenty_inverse().apply
- ( get_as_radian<0>(p1), get_as_radian<1>(p1),
- get_as_radian<0>(p2), get_as_radian<1>(p2),
- spheroid ).azimuth;
- }
-
- template
- static inline ReturnType apply(P1 const& p1, P2 const& p2)
- {
- return apply(p1, p2, srs::spheroid());
- }
-};
-
-template
-struct azimuth
-{
- template
- static inline ReturnType apply(P1 const& p1, P2 const& p2, Sphere const& /*unused*/)
- {
- return geometry::formula::spherical_azimuth
- ( get_as_radian<0>(p1), get_as_radian<1>(p1),
- get_as_radian<0>(p2), get_as_radian<1>(p2)).azimuth;
- }
-
- template
- static inline ReturnType apply(P1 const& p1, P2 const& p2)
- {
- return apply(p1, p2, 0); // dummy model
- }
-};
-
-template
-struct azimuth
- : azimuth
-{};
-
-template
-struct azimuth
-{
- template
- static inline ReturnType apply(P1 const& p1, P2 const& p2, Plane const& /*unused*/)
- {
- ReturnType x = get<0>(p2) - get<0>(p1);
- ReturnType y = get<1>(p2) - get<1>(p1);
-
- // NOTE: azimuth 0 is at Y axis, increasing right
- // as in spherical/geographic where 0 is at North axis
- return atan2(x, y);
- }
-
- template
- static inline ReturnType apply(P1 const& p1, P2 const& p2)
- {
- return apply(p1, p2, 0); // dummy model
- }
-};
-
-} // detail_dispatch
-#endif // DOXYGEN_NO_DISPATCH
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-
-/// Calculate azimuth between two points.
-/// The result is in radians.
-template
-inline ReturnType azimuth(Point1 const& p1, Point2 const& p2)
-{
- return detail_dispatch::azimuth
- <
- ReturnType,
- typename geometry::cs_tag::type
- >::apply(p1, p2);
-}
-
-/// Calculate azimuth between two points.
-/// The result is in radians.
-template
-inline ReturnType azimuth(Point1 const& p1, Point2 const& p2, Model const& model)
-{
- return detail_dispatch::azimuth
- <
- ReturnType,
- typename geometry::cs_tag::type
- >::apply(p1, p2, model);
-}
-
-} // namespace detail
-#endif // DOXYGEN_NO_DETAIL
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_AZIMUTH_HPP
diff --git a/include/boost/geometry/algorithms/detail/course.hpp b/include/boost/geometry/algorithms/detail/course.hpp
deleted file mode 100644
index 37424941b..000000000
--- a/include/boost/geometry/algorithms/detail/course.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Boost.Geometry (aka GGL, Generic Geometry Library)
-
-// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
-
-// This file was modified by Oracle on 2014.
-// Modifications copyright (c) 2014, 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_ALGORITHMS_DETAIL_COURSE_HPP
-#define BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
-
-#include
-
-namespace boost { namespace geometry
-{
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-
-/// Calculate course (bearing) between two points.
-///
-/// NOTE: left for convenience and temporary backward compatibility
-template
-inline ReturnType course(Point1 const& p1, Point2 const& p2)
-{
- return azimuth(p1, p2);
-}
-
-} // namespace detail
-#endif // DOXYGEN_NO_DETAIL
-
-}} // namespace boost::geometry
-
-#endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_COURSE_HPP
diff --git a/include/boost/geometry/geometry.hpp b/include/boost/geometry/geometry.hpp
index 24b12fab7..9aff956c9 100644
--- a/include/boost/geometry/geometry.hpp
+++ b/include/boost/geometry/geometry.hpp
@@ -4,8 +4,8 @@
// Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
-// This file was modified by Oracle on 2014-2020.
-// Modifications copyright (c) 2014-2020 Oracle and/or its affiliates.
+// This file was modified by Oracle on 2014-2021.
+// Modifications copyright (c) 2014-2021 Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -60,6 +60,7 @@ BOOST_PRAGMA_MESSAGE("CAUTION: Define BOOST_GEOMETRY_DISABLE_DEPRECATED_03_WARNI
#include
#include
#include
+#include
#include
#include
#include
diff --git a/include/boost/geometry/strategies/azimuth.hpp b/include/boost/geometry/strategies/azimuth.hpp
index 1573ad22a..7d1e105d9 100644
--- a/include/boost/geometry/strategies/azimuth.hpp
+++ b/include/boost/geometry/strategies/azimuth.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2016-2020 Oracle and/or its affiliates.
+// Copyright (c) 2016-2021 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
@@ -26,7 +26,7 @@ namespace strategy { namespace azimuth { namespace services
\tparam CSTag tag of coordinate system
\tparam CalculationType \tparam_calculation
*/
-template
+template
struct default_strategy
{
BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
diff --git a/include/boost/geometry/strategies/azimuth/cartesian.hpp b/include/boost/geometry/strategies/azimuth/cartesian.hpp
new file mode 100644
index 000000000..ac6136f89
--- /dev/null
+++ b/include/boost/geometry/strategies/azimuth/cartesian.hpp
@@ -0,0 +1,63 @@
+// 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_STRATEGIES_AZIMUTH_CARTESIAN_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_CARTESIAN_HPP
+
+
+// TODO: move this file to boost/geometry/strategy
+#include
+
+#include
+#include
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategies { namespace azimuth
+{
+
+template
+struct cartesian : strategies::detail::cartesian_base
+{
+ static auto azimuth()
+ {
+ return strategy::azimuth::cartesian();
+ }
+};
+
+
+namespace services
+{
+
+template
+struct default_strategy
+{
+ using type = strategies::azimuth::cartesian<>;
+};
+
+
+template
+struct strategy_converter >
+{
+ static auto get(strategy::azimuth::cartesian const&)
+ {
+ return strategies::azimuth::cartesian();
+ }
+};
+
+
+} // namespace services
+
+}} // namespace strategies::azimuth
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_CARTESIAN_HPP
diff --git a/include/boost/geometry/strategies/azimuth/geographic.hpp b/include/boost/geometry/strategies/azimuth/geographic.hpp
new file mode 100644
index 000000000..a4fac5e60
--- /dev/null
+++ b/include/boost/geometry/strategies/azimuth/geographic.hpp
@@ -0,0 +1,81 @@
+// 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_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP
+
+
+// TODO: move this file to boost/geometry/strategy
+#include
+
+#include
+#include
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategies { namespace azimuth
+{
+
+template
+<
+ typename FormulaPolicy = strategy::andoyer,
+ typename Spheroid = srs::spheroid,
+ typename CalculationType = void
+>
+class geographic : strategies::detail::geographic_base
+{
+ using base_t = strategies::detail::geographic_base;
+
+public:
+ geographic()
+ : base_t()
+ {}
+
+ explicit geographic(Spheroid const& spheroid)
+ : base_t(spheroid)
+ {}
+
+ auto azimuth() const
+ {
+ return strategy::azimuth::geographic
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ >(base_t::m_spheroid);
+ }
+};
+
+
+namespace services
+{
+
+template
+struct default_strategy
+{
+ using type = strategies::azimuth::geographic<>;
+};
+
+
+template
+struct strategy_converter >
+{
+ static auto get(strategy::azimuth::geographic const& strategy)
+ {
+ return strategies::azimuth::geographic(strategy.model());
+ }
+};
+
+} // namespace services
+
+}} // namespace strategies::azimuth
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_GEOGRAPHIC_HPP
diff --git a/include/boost/geometry/strategies/azimuth/services.hpp b/include/boost/geometry/strategies/azimuth/services.hpp
new file mode 100644
index 000000000..11980e5a4
--- /dev/null
+++ b/include/boost/geometry/strategies/azimuth/services.hpp
@@ -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_STRATEGIES_AZIMUTH_SERVICES_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SERVICES_HPP
+
+
+#include
+#include
+
+
+namespace boost { namespace geometry
+{
+
+
+namespace strategies { namespace azimuth {
+
+namespace services
+{
+
+template
+<
+ typename Point1, typename Point2,
+ typename CSTag1 = typename geometry::cs_tag::type,
+ typename CSTag2 = typename geometry::cs_tag::type
+>
+struct default_strategy
+{
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
+ "Not implemented for these Points' coordinate systems.",
+ Point1, Point2, CSTag1, CSTag2);
+};
+
+template
+struct strategy_converter
+{
+ BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
+ "Not implemented for this Strategy.",
+ Strategy);
+};
+
+
+} // namespace services
+
+}} // namespace strategies::azimuth
+
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SERVICES_HPP
diff --git a/include/boost/geometry/strategies/azimuth/spherical.hpp b/include/boost/geometry/strategies/azimuth/spherical.hpp
new file mode 100644
index 000000000..a87cf927b
--- /dev/null
+++ b/include/boost/geometry/strategies/azimuth/spherical.hpp
@@ -0,0 +1,67 @@
+// 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_STRATEGIES_AZIMUTH_SPHERICAL_HPP
+#define BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SPHERICAL_HPP
+
+
+// TODO: move this file to boost/geometry/strategy
+#include
+
+#include
+#include
+
+
+namespace boost { namespace geometry
+{
+
+namespace strategies { namespace azimuth
+{
+
+template
+class spherical : strategies::detail::spherical_base
+{
+ using base_t = strategies::detail::spherical_base;
+
+public:
+
+ static auto azimuth()
+ {
+ return strategy::azimuth::spherical();
+ }
+};
+
+
+namespace services
+{
+
+
+template
+struct default_strategy
+{
+ using type = strategies::azimuth::spherical<>;
+};
+
+template
+struct strategy_converter >
+{
+ static auto get(strategy::azimuth::spherical const&)
+ {
+ return strategies::azimuth::spherical();
+ }
+};
+
+
+} // namespace services
+
+}} // namespace strategies::azimuth
+
+}} // namespace boost::geometry
+
+#endif // BOOST_GEOMETRY_STRATEGIES_AZIMUTH_SPHERICAL_HPP
diff --git a/include/boost/geometry/strategies/cartesian.hpp b/include/boost/geometry/strategies/cartesian.hpp
index 76d84caf3..9b4559ad4 100644
--- a/include/boost/geometry/strategies/cartesian.hpp
+++ b/include/boost/geometry/strategies/cartesian.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,6 +12,7 @@
#include
+#include
#include
#include
#include
@@ -35,7 +36,10 @@ class cartesian
{
public:
- // point_order
+ static auto azimuth()
+ {
+ return strategy::azimuth::cartesian();
+ }
static auto point_order()
{
diff --git a/include/boost/geometry/strategies/cartesian/azimuth.hpp b/include/boost/geometry/strategies/cartesian/azimuth.hpp
index 2ff16e945..74a9ea12b 100644
--- a/include/boost/geometry/strategies/cartesian/azimuth.hpp
+++ b/include/boost/geometry/strategies/cartesian/azimuth.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2016-2018 Oracle and/or its affiliates.
+// Copyright (c) 2016-2021 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
@@ -11,32 +11,81 @@
#ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_AZIMUTH_HPP
+#include
+
#include
#include
+#include
+#include
+
namespace boost { namespace geometry
{
namespace strategy { namespace azimuth
{
-template
-<
- typename CalculationType = void
->
+template
class cartesian
-{};
+{
+public:
+ template
+ struct result_type
+ : geometry::select_most_precise
+ <
+ // NOTE: this promotes any integer type to double
+ typename geometry::promote_floating_point::type,
+ typename geometry::promote_floating_point::type,
+ CalculationType
+ >
+ {};
+
+ template
+ static inline void apply(T1 const& x1, T1 const& y1,
+ T2 const& x2, T2 const& y2,
+ Result& a1, Result& a2)
+ {
+ compute(x1, y1, x2, y2, a1, a2);
+ }
+ template
+ static inline void apply(T1 const& x1, T1 const& y1,
+ T2 const& x2, T2 const& y2,
+ Result& a1)
+ {
+ compute(x1, y1, x2, y2, a1, a1);
+ }
+ template
+ static inline void apply_reverse(T1 const& x1, T1 const& y1,
+ T2 const& x2, T2 const& y2,
+ Result& a2)
+ {
+ compute(x1, y1, x2, y2, a2, a2);
+ }
+
+private:
+ template
+ static inline void compute(T1 const& x1, T1 const& y1,
+ T2 const& x2, T2 const& y2,
+ Result& a1, Result& a2)
+ {
+ typedef typename result_type::type calc_t;
+
+ // NOTE: azimuth 0 is at Y axis, increasing right
+ // as in spherical/geographic where 0 is at North axis
+ a1 = a2 = atan2(calc_t(x2) - calc_t(x1), calc_t(y2) - calc_t(y1));
+ }
+};
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
namespace services
{
-template
-struct default_strategy
+template <>
+struct default_strategy
{
- typedef strategy::azimuth::cartesian type;
+ typedef strategy::azimuth::cartesian<> type;
};
}
diff --git a/include/boost/geometry/strategies/geographic.hpp b/include/boost/geometry/strategies/geographic.hpp
index b20b2574a..815f1e3f3 100644
--- a/include/boost/geometry/strategies/geographic.hpp
+++ b/include/boost/geometry/strategies/geographic.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,6 +12,7 @@
#include
+#include
#include
#include
#include
@@ -50,6 +51,14 @@ public:
: base_t(spheroid)
{}
+ auto azimuth() const
+ {
+ return strategy::azimuth::geographic
+ <
+ FormulaPolicy, Spheroid, CalculationType
+ >(base_t::m_spheroid);
+ }
+
auto point_order() const
{
return strategy::point_order::geographic
diff --git a/include/boost/geometry/strategies/geographic/azimuth.hpp b/include/boost/geometry/strategies/geographic/azimuth.hpp
index ca280313d..9e6914d92 100644
--- a/include/boost/geometry/strategies/geographic/azimuth.hpp
+++ b/include/boost/geometry/strategies/geographic/azimuth.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2016-2020 Oracle and/or its affiliates.
+// Copyright (c) 2016-2021 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
@@ -19,6 +19,8 @@
#include
#include
+#include
+
namespace boost { namespace geometry
{
@@ -34,7 +36,14 @@ template
>
class geographic
{
-public :
+public:
+ template
+ struct result_type
+ : geometry::select_most_precise
+ <
+ T1, T2, CalculationType
+ >
+ {};
typedef Spheroid model_type;
@@ -51,28 +60,28 @@ public :
return m_spheroid;
}
- template
- inline void apply(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a1, T& a2) const
+ template
+ inline void apply(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a1, Result& a2) const
{
compute(lon1_rad, lat1_rad,
lon2_rad, lat2_rad,
a1, a2);
}
- template
- inline void apply(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a1) const
+ template
+ inline void apply(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a1) const
{
compute(lon1_rad, lat1_rad,
lon2_rad, lat2_rad,
a1, a1);
}
- template
- inline void apply_reverse(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a2) const
+ template
+ inline void apply_reverse(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a2) const
{
compute(lon1_rad, lat1_rad,
lon2_rad, lat2_rad,
@@ -85,16 +94,13 @@ private :
<
bool EnableAzimuth,
bool EnableReverseAzimuth,
- typename T
+ typename T1, typename T2, typename Result
>
- inline void compute(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a1, T& a2) const
+ inline void compute(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a1, Result& a2) const
{
- typedef std::conditional_t
- <
- std::is_void::value, T, CalculationType
- > calc_t;
+ typedef typename result_type::type calc_t;
typedef typename FormulaPolicy::template inverse
<
@@ -127,14 +133,13 @@ private :
namespace services
{
-template
-struct default_strategy
+template <>
+struct default_strategy
{
typedef strategy::azimuth::geographic
<
strategy::andoyer,
- srs::spheroid,
- CalculationType
+ srs::spheroid
> type;
};
diff --git a/include/boost/geometry/strategies/spherical.hpp b/include/boost/geometry/strategies/spherical.hpp
index f7d4cc8d7..07495e857 100644
--- a/include/boost/geometry/strategies/spherical.hpp
+++ b/include/boost/geometry/strategies/spherical.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry
-// Copyright (c) 2020, Oracle and/or its affiliates.
+// Copyright (c) 2020-2021, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
@@ -12,6 +12,7 @@
#include
+#include
#include
#include
#include
@@ -53,7 +54,10 @@ public:
>::apply(radius_or_sphere);
}
- // point_order
+ static auto azimuth()
+ {
+ return strategy::azimuth::spherical();
+ }
static auto point_order()
{
diff --git a/include/boost/geometry/strategies/spherical/azimuth.hpp b/include/boost/geometry/strategies/spherical/azimuth.hpp
index 32339057b..6fcb15ac9 100644
--- a/include/boost/geometry/strategies/spherical/azimuth.hpp
+++ b/include/boost/geometry/strategies/spherical/azimuth.hpp
@@ -1,6 +1,6 @@
// Boost.Geometry (aka GGL, Generic Geometry Library)
-// Copyright (c) 2016-2020 Oracle and/or its affiliates.
+// Copyright (c) 2016-2021 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
@@ -14,9 +14,12 @@
#include
-#include
#include
+#include
+
+#include
+
namespace boost { namespace geometry
{
@@ -24,61 +27,58 @@ namespace boost { namespace geometry
namespace strategy { namespace azimuth
{
-template
-<
- typename CalculationType = void
->
+template
class spherical
{
-public :
+public:
+ template
+ struct result_type
+ : geometry::select_most_precise
+ <
+ T1, T2, CalculationType
+ >
+ {};
- inline spherical()
- {}
-
- template
- inline void apply(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a1, T& a2) const
+ template
+ static inline void apply(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a1, Result& a2)
{
compute(lon1_rad, lat1_rad,
lon2_rad, lat2_rad,
a1, a2);
}
- template
- inline void apply(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a1) const
+ template
+ static inline void apply(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a1)
{
compute(lon1_rad, lat1_rad,
lon2_rad, lat2_rad,
a1, a1);
}
- template
- inline void apply_reverse(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a2) const
+ template
+ static inline void apply_reverse(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a2)
{
compute(lon1_rad, lat1_rad,
lon2_rad, lat2_rad,
a2, a2);
}
-private :
-
+private:
template
<
bool EnableAzimuth,
bool EnableReverseAzimuth,
- typename T
+ typename T1, typename T2, typename Result
>
- inline void compute(T const& lon1_rad, T const& lat1_rad,
- T const& lon2_rad, T const& lat2_rad,
- T& a1, T& a2) const
+ static inline void compute(T1 const& lon1_rad, T1 const& lat1_rad,
+ T2 const& lon2_rad, T2 const& lat2_rad,
+ Result& a1, Result& a2)
{
- typedef std::conditional_t
- <
- std::is_void::value, T, CalculationType
- > calc_t;
+ typedef typename result_type::type calc_t;
geometry::formula::result_spherical
result = geometry::formula::spherical_azimuth
@@ -104,19 +104,12 @@ private :
namespace services
{
-template
-struct default_strategy
+template <>
+struct default_strategy
{
- typedef strategy::azimuth::spherical type;
+ typedef strategy::azimuth::spherical<> type;
};
-/*
-template
-struct default_strategy
-{
- typedef strategy::azimuth::spherical type;
-};
-*/
}
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
diff --git a/test/algorithms/Jamfile b/test/algorithms/Jamfile
index 3846cdb12..db2d1ce67 100644
--- a/test/algorithms/Jamfile
+++ b/test/algorithms/Jamfile
@@ -5,8 +5,8 @@
# Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
# Copyright (c) 2018 Adam Wulkiewicz, Lodz, Poland.
#
-# This file was modified by Oracle on 2014, 2015, 2016, 2017.
-# Modifications copyright (c) 2014-2017, Oracle and/or its affiliates.
+# This file was modified by Oracle on 2014-2021.
+# Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
#
# Contributed and/or modified by Vissarion Fisikopoulos, on behalf of Oracle
# Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
@@ -20,6 +20,7 @@ test-suite boost-geometry-algorithms
:
[ run append.cpp : : : : algorithms_append ]
[ run assign.cpp : : : : algorithms_assign ]
+ [ run azimuth.cpp : : : : algorithms_azimuth ]
[ run centroid.cpp : : : : algorithms_centroid ]
[ run centroid_multi.cpp : : : : algorithms_centroid_multi ]
[ run comparable_distance.cpp : : : : algorithms_comparable_distance ]
diff --git a/test/algorithms/azimuth.cpp b/test/algorithms/azimuth.cpp
new file mode 100644
index 000000000..541884771
--- /dev/null
+++ b/test/algorithms/azimuth.cpp
@@ -0,0 +1,88 @@
+// Boost.Geometry
+// Unit Test
+
+// 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
+
+
+#include
+
+#include
+
+#include
+
+
+template
+auto call_azimuth(P const& p1, P const& p2, S const& s)
+{
+ return bg::azimuth(p1, p2, s);
+}
+
+template
+auto call_azimuth(P const& p1, P const& p2, bg::default_strategy const&)
+{
+ return bg::azimuth(p1, p2);
+}
+
+template
+void test_one(P const& p1, P const& p2, double expected, S const& s = S())
+{
+ double const result = call_azimuth(p1, p2, s) * bg::math::r2d();
+ BOOST_CHECK_CLOSE(result, expected, 0.0001);
+}
+
+template
+void test_car()
+{
+ test_one(P(0, 0), P(0, 0), 0);
+ test_one(P(0, 0), P(1, 1), 45);
+ test_one(P(0, 0), P(100, 1), 89.427061302316517);
+ test_one(P(0, 0), P(-1, 1), -45);
+ test_one(P(0, 0), P(-100, 1), -89.427061302316517);
+}
+
+template
+void test_sph()
+{
+ test_one(P(0, 0), P(0, 0), 0);
+ test_one(P(0, 0), P(1, 1), 44.995636455344851);
+ test_one(P(0, 0), P(100, 1), 88.984576593576293);
+ test_one(P(0, 0), P(-1, 1), -44.995636455344851);
+ test_one(P(0, 0), P(-100, 1), -88.984576593576293);
+}
+
+template
+void test_geo()
+{
+ test_one(P(0, 0), P(0, 0), 0);
+ test_one(P(0, 0), P(1, 1), 45.187718848049521);
+ test_one(P(0, 0), P(100, 1), 88.986933066023497);
+ test_one(P(0, 0), P(-1, 1), -45.187718848049521);
+ test_one(P(0, 0), P(-100, 1), -88.986933066023497);
+}
+
+template
+void test_geo_v()
+{
+ bg::strategies::azimuth::geographic s;
+
+ test_one(P(0, 0), P(0, 0), 0, s);
+ test_one(P(0, 0), P(1, 1), 45.188040229339755, s);
+ test_one(P(0, 0), P(100, 1), 88.986914518230208, s);
+ test_one(P(0, 0), P(-1, 1), -45.188040229339755, s);
+ test_one(P(0, 0), P(-100, 1), -88.986914518230208, s);
+}
+
+int test_main(int, char* [])
+{
+ test_car< bg::model::point >();
+ test_sph< bg::model::point > >();
+ test_geo< bg::model::point > >();
+ test_geo_v< bg::model::point > >();
+
+ return 0;
+}