Skip to content

Commit aa024f3

Browse files
committed
Separate meridian-parallel polygons
1 parent 4778f09 commit aa024f3

File tree

6 files changed

+153
-69
lines changed

6 files changed

+153
-69
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ HEADERS = constants.h functions.h haversine.h vincenty.h greatcircle.h karney.h
1111
all: debug
1212
@strip bin/geodesic
1313

14-
debug: src/haversine.o src/vincenty.o src/main.o src/io.o src/math.o src/greatcircle.o src/karney.o
14+
debug: src/haversine.o src/vincenty.o src/main.o src/io.o src/math.o src/greatcircle.o src/karney.o src/mpblock.o
1515
@mkdir -p bin
1616
$(CC) $(CFLAGS) -o bin/geodesic $^ $(LDFLAGS)
1717

include/geodesic.h

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define FLAT (1.0l/298.257223563l)
1414

1515
#define RAD_MIN (RAD_MAJ * (1.0l - FLAT))
16+
#define FLAT_3 ((RAD_MAJ - RAD_MIN) / (RAD_MAJ + RAD_MIN))
1617
#define ECC (FLAT * (2.0l - FLAT))
1718
#define ECC2 (ECC / (1.0l - ECC))
1819

include/mpblock.h

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "geodesic.h"
2+
3+
#ifndef __HAVE_MPBLOCK_H__
4+
5+
#define __HAVE_MPBLOCK_H__
6+
7+
void mpblock(struct Coordinates *vertex, int i, long double s, long double a, long double *res);
8+
9+
#endif

src/karney.c

-68
Original file line numberDiff line numberDiff line change
@@ -83,84 +83,16 @@ long double I4(long double csig, long double salp)
8383
return i;
8484
}
8585

86-
int isblock(struct Coordinates *vertex)
87-
{
88-
int block = 1;
89-
block &= (vertex->lat == (vertex + 1)->lat && (vertex + 2)->lat == (vertex + 3)->lat && (vertex + 1)->lon == (vertex + 2)->lon && vertex->lon == (vertex + 3)->lon);
90-
block |= (vertex->lon == (vertex + 1)->lon && (vertex + 2)->lon == (vertex + 3)->lon && (vertex + 1)->lat == (vertex + 2)->lat && vertex->lat == (vertex + 3)->lat);
91-
return block;
92-
}
93-
94-
int ispolariso(struct Coordinates *vertex)
95-
{
96-
int k;
97-
for (k = 0; k < 3; k++) {
98-
if (fabsl((vertex + k)->lat) / RAD == 90 && (vertex + (k + 1) % 3)->lat == (vertex + (k + 2) % 3)->lat)
99-
break;
100-
}
101-
return k;
102-
}
103-
104-
long double ellipblock(struct Coordinates *vertex)
105-
{
106-
long double lat[2], lon[2];
107-
if (vertex->lat < (vertex + 2)->lat) {
108-
lat[0] = vertex->lat;
109-
lat[1] = (vertex + 2)->lat;
110-
}
111-
else {
112-
lat[0] = (vertex + 2)->lat;
113-
lat[1] = vertex->lat;
114-
}
115-
116-
if (vertex->lon < (vertex + 2)->lon) {
117-
lon[0] = vertex->lon;
118-
lon[1] = (vertex + 2)->lon;
119-
}
120-
else {
121-
lon[0] = (vertex + 2)->lon;
122-
lon[1] = vertex->lon;
123-
}
124-
125-
long double londiff = fabsl(normalise_c(lon[1] - lon[0]));
126-
long double latdiff = sinl(lat[1]) / (1.0l - ECC * sqr(sinl(lat[1]))) - sinl(lat[0]) / (1.0l - ECC * sqr(sinl(lat[0])));
127-
latdiff += logl((1.0l + sqrtl(ECC) * sinl(lat[1])) * (1.0l - sqrtl(ECC) * sinl(lat[0])) / (1.0l - sqrtl(ECC) * sinl(lat[1])) / (1.0l + sqrtl(ECC) * sinl(lat[0]))) / (2.0l * sqrtl(ECC));
128-
129-
return sqr(RAD_MIN) * londiff * latdiff / 2.0l;
130-
}
131-
13286
void karney(struct Coordinates *vertex, int i, int s, int a, long double *res)
13387
{
13488
long double *inter = malloc(sizeof(long double) * 8);
13589
long double prev, next, excess = 0;
13690
long double area, darea = 0, interarea;
13791
long double sig0, sig1;
138-
13992
long double perimeter = 0;
14093

14194
int h, k;
14295

143-
if (a == 1) {
144-
if (i == 4 && isblock(vertex)) {
145-
area = ellipblock(vertex);
146-
a = 0;
147-
}
148-
else if (i == 3 && (k = ispolariso(vertex)) < 3) {
149-
struct Coordinates *triangle = malloc(sizeof(struct Coordinates) * 4);
150-
151-
triangle->lat = (vertex + k)->lat;
152-
triangle->lon = (vertex + ((k + 2) % 3))->lon;
153-
memcpy(triangle + 1, vertex + ((k + 1) % 3), sizeof(struct Coordinates));
154-
for (h = 2; h < 4; h++) {
155-
(triangle + h)->lat = (vertex + ((k + h) % 3))->lat;
156-
(triangle + h)->lon = (triangle + (3 - h))->lon;
157-
}
158-
area = ellipblock(triangle);
159-
free(triangle);
160-
a = 0;
161-
}
162-
}
163-
16496
struct Coordinates *coor0, *coor1;
16597
for (h = 0; h < i; h++) {
16698
coor0 = vertex + h;

src/main.c

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "vincenty.h"
1111
#include "greatcircle.h"
1212
#include "karney.h"
13+
#include "mpblock.h"
1314

1415
void help(char *name)
1516
{
@@ -83,6 +84,8 @@ int main(int argc, char **argv)
8384
j = 1;
8485
else if (strcmp(optarg, "ellipsoid") == 0)
8586
j = 2;
87+
else if (strcmp(optarg, "block") == 0)
88+
j = 3;
8689
else
8790
error("Invalid formula.");
8891
break;
@@ -144,6 +147,9 @@ int main(int argc, char **argv)
144147
start = *(res + 1);
145148
end = *(res + 2);
146149
break;
150+
default:
151+
error("Formula not available for inverse problem.");
152+
break;
147153
}
148154

149155
if (isnan(c) && memcmp(location, location + 1, sizeof(struct Coordinates)) == 0)
@@ -200,6 +206,9 @@ int main(int argc, char **argv)
200206
(point + 1)->lon = *(res + 1);
201207
end = *(res + 2);
202208
break;
209+
default:
210+
error("Formula not available for direct problem.");
211+
break;
203212
}
204213

205214
if ((isnan((point + 1)->lat) || isnan((point + 1)->lon)) && add->s == 0)
@@ -264,6 +273,13 @@ int main(int argc, char **argv)
264273
perimeter = *res;
265274
area = *(res + 1);
266275
break;
276+
case 3:
277+
mpblock(vertex, i, distance, azimuth, res);
278+
perimeter = *res;
279+
area = *(res + 1);
280+
if (isnan(area) && isnan(perimeter))
281+
error("Not a meridian-parallel block.");
282+
break;
267283
}
268284
}
269285
else {

src/mpblock.c

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include <math.h>
2+
#include "mpblock.h"
3+
4+
long double double_fac(int x)
5+
{
6+
if (x == -3)
7+
return -1;
8+
else {
9+
long double y = 1;
10+
while (x > 0) {
11+
y *= x;
12+
x -= 2;
13+
}
14+
return y;
15+
}
16+
}
17+
18+
int isblock(struct Coordinates *vertex)
19+
{
20+
int block = 1;
21+
block &= (vertex->lat == (vertex + 1)->lat && (vertex + 2)->lat == (vertex + 3)->lat && (vertex + 1)->lon == (vertex + 2)->lon && vertex->lon == (vertex + 3)->lon);
22+
block |= (vertex->lon == (vertex + 1)->lon && (vertex + 2)->lon == (vertex + 3)->lon && (vertex + 1)->lat == (vertex + 2)->lat && vertex->lat == (vertex + 3)->lat);
23+
return block;
24+
}
25+
26+
int ispolariso(struct Coordinates *vertex)
27+
{
28+
int k;
29+
for (k = 0; k < 3; k++) {
30+
if (fabsl((vertex + k)->lat) / RAD == 90 && (vertex + (k + 1) % 3)->lat == (vertex + (k + 2) % 3)->lat)
31+
break;
32+
}
33+
return k;
34+
}
35+
36+
long double ellipblock(long double lat0, long double lat1, long double lon0, long double lon1)
37+
{
38+
long double londiff = fabsl(normalise_c(lon1 - lon0));
39+
long double latdiff = sinl(lat1) / (1.0l - ECC * sqr(sinl(lat1))) - sinl(lat0) / (1.0l - ECC * sqr(sinl(lat0)));
40+
latdiff += logl((1.0l + sqrtl(ECC) * sinl(lat1)) * (1.0l - sqrtl(ECC) * sinl(lat0)) / (1.0l - sqrtl(ECC) * sinl(lat1)) / (1.0l + sqrtl(ECC) * sinl(lat0))) / (2.0l * sqrtl(ECC));
41+
42+
return sqr(RAD_MIN) * londiff * latdiff / 2.0l;
43+
}
44+
45+
long double parallel_length(long double lon0, long double lon1, long double lat)
46+
{
47+
return cosl(lat) * fabsl(normalise_c(lon1 - lon0)) / sqrtl(1.0l - ECC * sqr(sinl(lat)));
48+
}
49+
50+
long double meridian_arc(long double lat0, long double lat1)
51+
{
52+
int k, j;
53+
long double c = 0, m = 0;
54+
55+
for (j = 0; j < 11; j++)
56+
c += sqr(double_fac(2 * j - 3) / double_fac(2 * j)) * powl(FLAT_3, 2 * j);
57+
m += c * (lat1 - lat0);
58+
59+
for (k = 1; k < 6; k++) {
60+
c = 0;
61+
for (j = 0; j < 11; j++)
62+
c += double_fac(2 * j - 3) / double_fac(2 * j) * double_fac(2 * j + 2 * k - 3) / double_fac(2 * j + 2 * k) * powl(FLAT_3, k + 2 * j);
63+
c /= k;
64+
m += powl(-1.0l, k) * c * (sin(2.0l * lat1) - sin(2.0l * lat0));
65+
}
66+
67+
return (RAD_MAJ + RAD_MIN) / 2 * m;
68+
}
69+
70+
void mpblock(struct Coordinates *vertex, int i, long double s, long double a, long double *res)
71+
{
72+
int h, k;
73+
74+
if (i == 4 && isblock(vertex)) {
75+
long double lat[2], lon[2];
76+
if (vertex->lat < (vertex + 2)->lat) {
77+
lat[0] = vertex->lat;
78+
lat[1] = (vertex + 2)->lat;
79+
}
80+
else {
81+
lat[0] = (vertex + 2)->lat;
82+
lat[1] = vertex->lat;
83+
}
84+
85+
if (vertex->lon < (vertex + 2)->lon) {
86+
lon[0] = vertex->lon;
87+
lon[1] = (vertex + 2)->lon;
88+
}
89+
else {
90+
lon[0] = (vertex + 2)->lon;
91+
lon[1] = vertex->lon;
92+
}
93+
94+
if (a == 1)
95+
*(res + 1) = ellipblock(lat[0], lat[1], lon[0], lon[1]);
96+
if (s == 1) {
97+
*res = parallel_length(lat[0], lat[1], lon[0]);
98+
*res += parallel_length(lat[0], lat[1], lon[1]);
99+
*res += meridian_arc(lat[0], lat[1]) * 2.0l;
100+
}
101+
}
102+
else if (i == 3 && (k = ispolariso(vertex)) < 3) {
103+
long double lon[2];
104+
105+
if ((vertex + k + 1)->lon < (vertex + ((k + 2) % 3))->lon) {
106+
lon[0] = (vertex + k + 1)->lon;
107+
lon[1] = (vertex + ((k + 2) % 3))->lon;
108+
}
109+
else {
110+
lon[1] = (vertex + k + 1)->lon;
111+
lon[0] = (vertex + ((k + 2) % 3))->lon;
112+
}
113+
114+
if (a == 1)
115+
*(res + 1) = ellipblock((vertex + k + 1)->lat, (vertex + k)->lat, lon[0], lon[1]);
116+
if (s == 1) {
117+
*res = parallel_length(lon[0], lon[1], (vertex + k + 1)->lat);
118+
*res += meridian_arc((vertex + k + 1)->lat, (vertex + k)->lat) * 2.0l;
119+
}
120+
}
121+
else {
122+
*res = NAN;
123+
*(res + 1) = NAN;
124+
}
125+
return;
126+
}

0 commit comments

Comments
 (0)