GRASS 8 Programmer's Manual
8.5.0(2026)-8d6ceba290
Toggle main menu visibility
Loading...
Searching...
No Matches
area_poly1.c
Go to the documentation of this file.
1
/*!
2
* \file lib/gis/area_poly1.c
3
*
4
* \brief GIS Library - Polygon area calculation routines.
5
*
6
* (C) 2001-2013 by the GRASS Development Team
7
*
8
* This program is free software under the GNU General Public License
9
* (>=v2). Read the file COPYING that comes with GRASS for details.
10
*
11
* \author Original author CERL
12
*/
13
14
#include <math.h>
15
#include <grass/gis.h>
16
#include "
pi.h
"
17
18
#define TWOPI M_PI + M_PI
19
20
static
struct
state {
21
double
QA, QB, QC;
22
double
QbarA, QbarB, QbarC, QbarD;
23
24
double
AE;
/** a^2(1-e^2) */
25
26
double
Qp;
/** Q at the north pole */
27
28
double
E;
/** Area of the earth */
29
} state;
30
31
static
struct
state *st = &state;
32
33
static
double
Q(
double
x
)
34
{
35
double
sinx, sinx2;
36
37
sinx = sin(
x
);
38
sinx2 = sinx * sinx;
39
40
return
sinx * (1 + sinx2 * (st->QA + sinx2 * (st->QB + sinx2 * st->QC)));
41
}
42
43
static
double
Qbar(
double
x
)
44
{
45
double
cosx, cosx2;
46
47
cosx = cos(
x
);
48
cosx2 = cosx * cosx;
49
50
return
cosx *
51
(st->QbarA +
52
cosx2 * (st->QbarB + cosx2 * (st->QbarC + cosx2 * st->QbarD)));
53
}
54
55
/*!
56
* \brief Begin area calculations.
57
*
58
* This initializes the polygon area calculations for the
59
* ellipsoid with semi-major axis <i>a</i> (in meters) and ellipsoid
60
* eccentricity squared <i>e2</i>.
61
*
62
* \param a semi-major axis
63
* \param e2 ellipsoid eccentricity squared
64
*/
65
void
G_begin_ellipsoid_polygon_area
(
double
a,
double
e2)
66
{
67
double
e4, e6;
68
69
e4 = e2 * e2;
70
e6 = e4 * e2;
71
72
st->AE = a * a * (1 - e2);
73
74
st->QA = (2.0 / 3.0) * e2;
75
st->QB = (3.0 / 5.0) * e4;
76
st->QC = (4.0 / 7.0) * e6;
77
78
st->QbarA = -1.0 - (2.0 / 3.0) * e2 - (3.0 / 5.0) * e4 - (4.0 / 7.0) * e6;
79
st->QbarB = (2.0 / 9.0) * e2 + (2.0 / 5.0) * e4 + (4.0 / 7.0) * e6;
80
st->QbarC = -(3.0 / 25.0) * e4 - (12.0 / 35.0) * e6;
81
st->QbarD = (4.0 / 49.0) * e6;
82
83
st->Qp = Q(M_PI_2);
84
st->E = 4 * M_PI * st->Qp * st->AE;
85
if
(st->E < 0.0)
86
st->E = -st->E;
87
}
88
89
/*!
90
* \brief Area of lat-long polygon.
91
*
92
* Returns the area in square meters of the polygon described by the
93
* <i>n</i> pairs of <i>lat,long</i> vertices for latitude-longitude
94
* grids.
95
*
96
* <b>Note:</b> This routine computes the area of a polygon on the
97
* ellipsoid. The sides of the polygon are rhumb lines and, in general,
98
* not geodesics. Each side is actually defined by a linear relationship
99
* between latitude and longitude, i.e., on a rectangular/equidistant
100
* cylindrical/Plate Carr{'e}e grid, the side would appear as a
101
* straight line. For two consecutive vertices of the polygon,
102
* (lat_1, long1) and (lat_2,long_2), the line joining them (i.e., the
103
* polygon's side) is defined by:
104
*
105
\verbatim
106
lat_2 - lat_1
107
lat = lat_1 + (long - long_1) * ---------------
108
long_2 - long_1
109
\endverbatim
110
*
111
* where long_1 < long < long_2.
112
* The values of QbarA, etc., are determined by the integration of
113
* the Q function. Into www.integral-calculator.com, paste this
114
* expression :
115
*
116
\verbatim
117
sin(x)+ (2/3)e^2(sin(x))^3 + (3/5)e^4(sin(x))^5 + (4/7)e^6(sin(x))^7
118
\endverbatim
119
*
120
* and you'll get their values. (Last checked 30 Oct 2013).
121
*
122
* This function correctly computes (within the limits of the series
123
* approximation) the area of a quadrilateral on the ellipsoid when
124
* two of its sides run along meridians and the other two sides run
125
* along parallels of latitude.
126
*
127
* \param lon array of longitudes
128
* \param lat array of latitudes
129
* \param n number of lat,lon pairs
130
*
131
* \return area in square meters
132
*/
133
double
G_ellipsoid_polygon_area
(
const
double
*lon,
const
double
*lat,
int
n)
134
{
135
double
x1, y1, x2, y2, dx, dy;
136
double
Qbar1, Qbar2;
137
double
area;
138
double
thresh =
139
1e-6;
/* threshold for dy, should be between 1e-4 and 1e-7 */
140
141
x2 =
Radians
(lon[n - 1]);
142
y2 =
Radians
(lat[n - 1]);
143
Qbar2 = Qbar(y2);
144
145
area = 0.0;
146
147
while
(--n >= 0) {
148
x1 = x2;
149
y1 = y2;
150
Qbar1 = Qbar2;
151
152
x2 =
Radians
(*lon++);
153
y2 =
Radians
(*lat++);
154
Qbar2 = Qbar(y2);
155
156
if
(x1 > x2)
157
while
(x1 - x2 > M_PI)
158
x2 +=
TWOPI
;
159
else
if
(x2 > x1)
160
while
(x2 - x1 > M_PI)
161
x1 +=
TWOPI
;
162
163
dx = x2 - x1;
164
dy = y2 - y1;
165
166
if
(fabs(dy) > thresh) {
167
/* account for different latitudes y1, y2 */
168
area += dx * (st->Qp - (Qbar2 - Qbar1) / dy);
169
/* original:
170
* area += dx * st->Qp - (dx / dy) * (Qbar2 - Qbar1);
171
*/
172
}
173
else
{
174
/* latitudes y1, y2 are (nearly) identical */
175
/* if y2 becomes similar to y1, i.e. y2 -> y1
176
* Qbar2 - Qbar1 -> 0 and dy -> 0
177
* (Qbar2 - Qbar1) / dy -> ?
178
* (Qbar2 - Qbar1) / dy should approach Q((y1 + y2) / 2)
179
* Metz 2017
180
*/
181
area += dx * (st->Qp - Q((y1 + y2) / 2));
182
}
183
}
184
if
((area *= st->AE) < 0.0)
185
area = -area;
186
187
/* kludge - if polygon circles the south pole the area will be
188
* computed as if it circled the north pole. The correction is
189
* the difference between total surface area of the earth and
190
* the "north pole" area.
191
*/
192
if
(area > st->E)
193
area = st->E;
194
if
(area > st->E / 2)
195
area = st->E - area;
196
197
return
area;
198
}
TWOPI
#define TWOPI
Definition
area_poly1.c:18
G_begin_ellipsoid_polygon_area
void G_begin_ellipsoid_polygon_area(double a, double e2)
Begin area calculations.
Definition
area_poly1.c:65
G_ellipsoid_polygon_area
double G_ellipsoid_polygon_area(const double *lon, const double *lat, int n)
Area of lat-long polygon.
Definition
area_poly1.c:133
pi.h
Radians
#define Radians(x)
Definition
pi.h:6
x
#define x
gis
area_poly1.c
Generated on
for GRASS 8 Programmer's Manual by
1.17.0