Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/geometry/strategies/spherical/area_huiller.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // Boost.Geometry (aka GGL, Generic Geometry Library) | |
2 | |
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | |
5 // Use, modification and distribution is subject to the Boost Software License, | |
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
7 // http://www.boost.org/LICENSE_1_0.txt) | |
8 | |
9 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP | |
10 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP | |
11 | |
12 | |
13 | |
14 #include <boost/geometry/strategies/spherical/distance_haversine.hpp> | |
15 | |
16 #include <boost/geometry/core/radian_access.hpp> | |
17 #include <boost/geometry/util/math.hpp> | |
18 | |
19 | |
20 namespace boost { namespace geometry | |
21 { | |
22 | |
23 namespace strategy { namespace area | |
24 { | |
25 | |
26 | |
27 | |
28 /*! | |
29 \brief Area calculation by spherical excess / Huiller's formula | |
30 \ingroup strategies | |
31 \tparam PointOfSegment point type of segments of rings/polygons | |
32 \tparam CalculationType \tparam_calculation | |
33 \author Barend Gehrels. Adapted from: | |
34 - http://www.soe.ucsc.edu/~pang/160/f98/Gems/GemsIV/sph_poly.c | |
35 - http://williams.best.vwh.net/avform.htm | |
36 \note The version in Gems didn't account for polygons crossing the 180 meridian. | |
37 \note This version works for convex and non-convex polygons, for 180 meridian | |
38 crossing polygons and for polygons with holes. However, some cases (especially | |
39 180 meridian cases) must still be checked. | |
40 \note The version which sums angles, which is often seen, doesn't handle non-convex | |
41 polygons correctly. | |
42 \note The version which sums longitudes, see | |
43 http://trs-new.jpl.nasa.gov/dspace/bitstream/2014/40409/1/07-03.pdf, is simple | |
44 and works well in most cases but not in 180 meridian crossing cases. This probably | |
45 could be solved. | |
46 | |
47 \note This version is made for spherical equatorial coordinate systems | |
48 | |
49 \qbk{ | |
50 | |
51 [heading Example] | |
52 [area_with_strategy] | |
53 [area_with_strategy_output] | |
54 | |
55 | |
56 [heading See also] | |
57 [link geometry.reference.algorithms.area.area_2_with_strategy area (with strategy)] | |
58 } | |
59 | |
60 */ | |
61 template | |
62 < | |
63 typename PointOfSegment, | |
64 typename CalculationType = void | |
65 > | |
66 class huiller | |
67 { | |
68 typedef typename boost::mpl::if_c | |
69 < | |
70 boost::is_void<CalculationType>::type::value, | |
71 typename select_most_precise | |
72 < | |
73 typename coordinate_type<PointOfSegment>::type, | |
74 double | |
75 >::type, | |
76 CalculationType | |
77 >::type calculation_type; | |
78 | |
79 protected : | |
80 struct excess_sum | |
81 { | |
82 calculation_type sum; | |
83 | |
84 // Distances are calculated on unit sphere here | |
85 strategy::distance::haversine<calculation_type> distance_over_unit_sphere; | |
86 | |
87 | |
88 inline excess_sum() | |
89 : sum(0) | |
90 , distance_over_unit_sphere(1) | |
91 {} | |
92 inline calculation_type area(calculation_type radius) const | |
93 { | |
94 return - sum * radius * radius; | |
95 } | |
96 }; | |
97 | |
98 public : | |
99 typedef calculation_type return_type; | |
100 typedef PointOfSegment segment_point_type; | |
101 typedef excess_sum state_type; | |
102 | |
103 inline huiller(calculation_type radius = 1.0) | |
104 : m_radius(radius) | |
105 {} | |
106 | |
107 inline void apply(PointOfSegment const& p1, | |
108 PointOfSegment const& p2, | |
109 excess_sum& state) const | |
110 { | |
111 if (! geometry::math::equals(get<0>(p1), get<0>(p2))) | |
112 { | |
113 calculation_type const half = 0.5; | |
114 calculation_type const two = 2.0; | |
115 calculation_type const four = 4.0; | |
116 calculation_type const two_pi = two * geometry::math::pi<calculation_type>(); | |
117 calculation_type const half_pi = half * geometry::math::pi<calculation_type>(); | |
118 | |
119 // Distance p1 p2 | |
120 calculation_type a = state.distance_over_unit_sphere.apply(p1, p2); | |
121 | |
122 // Sides on unit sphere to south pole | |
123 calculation_type b = half_pi - geometry::get_as_radian<1>(p2); | |
124 calculation_type c = half_pi - geometry::get_as_radian<1>(p1); | |
125 | |
126 // Semi parameter | |
127 calculation_type s = half * (a + b + c); | |
128 | |
129 // E: spherical excess, using l'Huiller's formula | |
130 // [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2] | |
131 calculation_type E = four * atan(sqrt(geometry::math::abs(tan(s / two) | |
132 * tan((s - a) / two) | |
133 * tan((s - b) / two) | |
134 * tan((s - c) / two)))); | |
135 | |
136 E = geometry::math::abs(E); | |
137 | |
138 // In right direction: positive, add area. In left direction: negative, subtract area. | |
139 // Longitude comparisons are not so obvious. If one is negative, other is positive, | |
140 // we have to take the dateline into account. | |
141 // TODO: check this / enhance this, should be more robust. See also the "grow" for ll | |
142 // TODO: use minmax or "smaller"/"compare" strategy for this | |
143 calculation_type lon1 = geometry::get_as_radian<0>(p1) < 0 | |
144 ? geometry::get_as_radian<0>(p1) + two_pi | |
145 : geometry::get_as_radian<0>(p1); | |
146 | |
147 calculation_type lon2 = geometry::get_as_radian<0>(p2) < 0 | |
148 ? geometry::get_as_radian<0>(p2) + two_pi | |
149 : geometry::get_as_radian<0>(p2); | |
150 | |
151 if (lon2 < lon1) | |
152 { | |
153 E = -E; | |
154 } | |
155 | |
156 state.sum += E; | |
157 } | |
158 } | |
159 | |
160 inline return_type result(excess_sum const& state) const | |
161 { | |
162 return state.area(m_radius); | |
163 } | |
164 | |
165 private : | |
166 /// Radius of the sphere | |
167 calculation_type m_radius; | |
168 }; | |
169 | |
170 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
171 | |
172 namespace services | |
173 { | |
174 | |
175 | |
176 template <typename Point> | |
177 struct default_strategy<spherical_equatorial_tag, Point> | |
178 { | |
179 typedef strategy::area::huiller<Point> type; | |
180 }; | |
181 | |
182 // Note: spherical polar coordinate system requires "get_as_radian_equatorial" | |
183 /***template <typename Point> | |
184 struct default_strategy<spherical_polar_tag, Point> | |
185 { | |
186 typedef strategy::area::huiller<Point> type; | |
187 };***/ | |
188 | |
189 } // namespace services | |
190 | |
191 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS | |
192 | |
193 | |
194 }} // namespace strategy::area | |
195 | |
196 | |
197 | |
198 | |
199 }} // namespace boost::geometry | |
200 | |
201 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_AREA_HUILLER_HPP |