]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2011-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | ||
b32b8144 FG |
5 | // This file was modified by Oracle on 2014, 2017. |
6 | // Modifications copyright (c) 2014-2017 Oracle and/or its affiliates. | |
7c673cae FG |
7 | |
8 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
9 | ||
10 | // Use, modification and distribution is subject to the Boost Software License, | |
11 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
12 | // http://www.boost.org/LICENSE_1_0.txt) | |
13 | ||
14 | #ifndef BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP | |
15 | #define BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP | |
16 | ||
17 | ||
18 | #include <boost/core/ignore_unused.hpp> | |
19 | ||
20 | #include <boost/geometry/core/radius.hpp> | |
21 | ||
22 | #include <boost/geometry/util/math.hpp> | |
23 | #include <boost/geometry/util/promote_floating_point.hpp> | |
24 | #include <boost/geometry/util/select_calculation_type.hpp> | |
25 | ||
26 | #include <boost/geometry/strategies/side.hpp> | |
27 | #include <boost/geometry/strategies/spherical/ssf.hpp> | |
28 | ||
29 | ||
30 | namespace boost { namespace geometry | |
31 | { | |
32 | ||
33 | namespace strategy { namespace side | |
34 | { | |
35 | ||
36 | ||
37 | // An enumeration type defining types of mapping of geographical | |
38 | // latitude to spherical latitude. | |
39 | // See: http://en.wikipedia.org/wiki/Great_ellipse | |
40 | // http://en.wikipedia.org/wiki/Latitude#Auxiliary_latitudes | |
41 | enum mapping_type { mapping_geodetic, mapping_reduced, mapping_geocentric }; | |
42 | ||
43 | ||
44 | #ifndef DOXYGEN_NO_DETAIL | |
45 | namespace detail | |
46 | { | |
47 | ||
48 | template <typename Spheroid, mapping_type Mapping> | |
49 | struct mapper | |
50 | { | |
51 | explicit inline mapper(Spheroid const& /*spheroid*/) {} | |
52 | ||
53 | template <typename CalculationType> | |
54 | static inline CalculationType const& apply(CalculationType const& lat) | |
55 | { | |
56 | return lat; | |
57 | } | |
58 | }; | |
59 | ||
60 | template <typename Spheroid> | |
61 | struct mapper<Spheroid, mapping_reduced> | |
62 | { | |
63 | typedef typename promote_floating_point | |
64 | < | |
65 | typename radius_type<Spheroid>::type | |
66 | >::type fraction_type; | |
67 | ||
68 | explicit inline mapper(Spheroid const& spheroid) | |
69 | { | |
70 | fraction_type const a = geometry::get_radius<0>(spheroid); | |
71 | fraction_type const b = geometry::get_radius<2>(spheroid); | |
72 | b_div_a = b / a; | |
73 | } | |
74 | ||
75 | template <typename CalculationType> | |
76 | inline CalculationType apply(CalculationType const& lat) const | |
77 | { | |
78 | return atan(static_cast<CalculationType>(b_div_a) * tan(lat)); | |
79 | } | |
80 | ||
81 | fraction_type b_div_a; | |
82 | }; | |
83 | ||
84 | template <typename Spheroid> | |
85 | struct mapper<Spheroid, mapping_geocentric> | |
86 | { | |
87 | typedef typename promote_floating_point | |
88 | < | |
89 | typename radius_type<Spheroid>::type | |
90 | >::type fraction_type; | |
91 | ||
92 | explicit inline mapper(Spheroid const& spheroid) | |
93 | { | |
94 | fraction_type const a = geometry::get_radius<0>(spheroid); | |
95 | fraction_type const b = geometry::get_radius<2>(spheroid); | |
96 | sqr_b_div_a = b / a; | |
97 | sqr_b_div_a *= sqr_b_div_a; | |
98 | } | |
99 | ||
100 | template <typename CalculationType> | |
101 | inline CalculationType apply(CalculationType const& lat) const | |
102 | { | |
103 | return atan(static_cast<CalculationType>(sqr_b_div_a) * tan(lat)); | |
104 | } | |
105 | ||
106 | fraction_type sqr_b_div_a; | |
107 | }; | |
108 | ||
109 | } | |
110 | #endif // DOXYGEN_NO_DETAIL | |
111 | ||
112 | ||
113 | /*! | |
114 | \brief Check at which side of a geographical segment a point lies | |
115 | left of segment (> 0), right of segment (< 0), on segment (0). | |
116 | The check is performed by mapping the geographical coordinates | |
117 | to spherical coordinates and using spherical_side_formula. | |
118 | \ingroup strategies | |
119 | \tparam Spheroid The reference spheroid model | |
120 | \tparam Mapping The type of mapping of geographical to spherical latitude | |
121 | \tparam CalculationType \tparam_calculation | |
122 | */ | |
123 | template <typename Spheroid, | |
124 | mapping_type Mapping = mapping_geodetic, | |
125 | typename CalculationType = void> | |
126 | class mapping_spherical_side_formula | |
127 | { | |
128 | ||
129 | public : | |
130 | inline mapping_spherical_side_formula() | |
131 | : m_mapper(Spheroid()) | |
132 | {} | |
133 | ||
134 | explicit inline mapping_spherical_side_formula(Spheroid const& spheroid) | |
135 | : m_mapper(spheroid) | |
136 | {} | |
137 | ||
138 | template <typename P1, typename P2, typename P> | |
b32b8144 | 139 | inline int apply(P1 const& p1, P2 const& p2, P const& p) const |
7c673cae FG |
140 | { |
141 | typedef typename promote_floating_point | |
142 | < | |
143 | typename select_calculation_type_alt | |
144 | < | |
145 | CalculationType, | |
146 | P1, P2, P | |
147 | >::type | |
148 | >::type calculation_type; | |
149 | ||
150 | calculation_type lon1 = get_as_radian<0>(p1); | |
151 | calculation_type lat1 = m_mapper.template apply<calculation_type>(get_as_radian<1>(p1)); | |
152 | calculation_type lon2 = get_as_radian<0>(p2); | |
153 | calculation_type lat2 = m_mapper.template apply<calculation_type>(get_as_radian<1>(p2)); | |
154 | calculation_type lon = get_as_radian<0>(p); | |
155 | calculation_type lat = m_mapper.template apply<calculation_type>(get_as_radian<1>(p)); | |
156 | ||
157 | return detail::spherical_side_formula(lon1, lat1, lon2, lat2, lon, lat); | |
158 | } | |
159 | ||
160 | private: | |
161 | side::detail::mapper<Spheroid, Mapping> const m_mapper; | |
162 | }; | |
163 | ||
164 | // The specialization for geodetic latitude which can be used directly | |
165 | template <typename Spheroid, | |
166 | typename CalculationType> | |
167 | class mapping_spherical_side_formula<Spheroid, mapping_geodetic, CalculationType> | |
168 | { | |
169 | ||
170 | public : | |
171 | inline mapping_spherical_side_formula() {} | |
172 | explicit inline mapping_spherical_side_formula(Spheroid const& /*spheroid*/) {} | |
173 | ||
174 | template <typename P1, typename P2, typename P> | |
175 | static inline int apply(P1 const& p1, P2 const& p2, P const& p) | |
176 | { | |
177 | return spherical_side_formula<CalculationType>::apply(p1, p2, p); | |
178 | } | |
179 | }; | |
180 | ||
181 | }} // namespace strategy::side | |
182 | ||
183 | }} // namespace boost::geometry | |
184 | ||
185 | #endif // BOOST_GEOMETRY_STRATEGIES_GEOGRAPHIC_MAPPING_SSF_HPP |