Skip to content

Commit 78bed3d

Browse files
committed
Added -g/--grid and -r/--random options
1 parent 3088aa3 commit 78bed3d

File tree

1 file changed

+73
-33
lines changed

1 file changed

+73
-33
lines changed

mapcode.c

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,48 @@ static void usage(const char* appName) {
2121
printf(" Encode a lat/lon to a Mapcode. If the territory code is specified, the\n");
2222
printf(" encoding will only succeeed if the lat/lon is located in the territory.\n");
2323
printf("\n");
24-
printf(" %s [-g | --generate] <nrPoints> [<seed>]\n", appName);
24+
printf(" %s [-g | --grid] <nrPoints> [<seed>]\n", appName);
25+
printf(" %s [-r | --random] <nrPoints> [<seed>]\n", appName);
2526
printf("\n");
26-
printf(" Create a test set of a number of uniformly distributed lat/lon pairs,\n");
27-
printf(" 3D x/y/z points and their Mapcodes). The output format is:\n");
28-
printf(" <nr> <lat> <lon> <x> <y> <z>\n");
29-
printf(" <territory> <mapcode> (repeated 'nr' rtimes)\n");
30-
printf(" <1 empty line>\n");
27+
printf(" Create a test set of a number of a grid or random uniformly distributed\n");
28+
printf(" lat/lon pairs, (x, y, z) points and the Mapcode aliases.\n");
3129
printf("\n");
32-
printf(" The points will be uniformly distributed over the 3D surface of the Earth\n");
33-
printf(" rather than using uniformly distributed lat/lon values.\n");
30+
printf(" The output format is:\n");
31+
printf(" <number-of-aliases> <lat-deg> <lon-deg> <x> <y> <z>\n");
32+
printf(" <territory> <mapcode> (repeated 'number-of-aliases' times)\n");
33+
printf(" (empty lines and next record)\n");
3434
printf(" Ranges:\n");
35-
printf(" nr > 1 lat = -90..90 lon = -180..180 x,y,z = -1..1\n");
35+
printf(" number-of-aliases : >= 1\n");
36+
printf(" lat-deg, lon-deg : [-90..90], [-180..180]\n");
37+
printf(" x, y, z : [-1..1]\n");
3638
printf("\n");
39+
printf(" The lat/lon pairs will be distributed over the 3D surface of the Earth\n");
40+
printf(" and the (x, y, z) coordinates are placed on a sphere with radius 1.\n");
41+
}
42+
43+
/**
44+
* Given a single number between 0..1, generate a latitude, longitude (in degrees) and a 3D
45+
* (x, y, z) point on a sphere with a radius of 1.
46+
*/
47+
static void unitToLatLonDegXYZ(
48+
const double unit, double* latDeg, double* lonDeg, double* x, double* y, double* z) {
49+
50+
// Calculate uniformly distributed 3D point on sphere (radius = 1.0):
51+
// http://mathproofs.blogspot.co.il/2005/04/uniform-random-distribution-on-sphere.html
52+
const double theta0 = (2.0 * PI) * unit;
53+
const double theta1 = acos(1.0 - (2.0 * unit));
54+
*x = sin(theta0) * sin(theta1);
55+
*y = cos(theta0) * sin(theta1);
56+
*z = cos(theta1);
57+
58+
// Convert Carthesian 3D point into lat/lon (radius = 1.0):
59+
// http://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates
60+
const double latRad = asin(*z);
61+
const double lonRad = atan2(*y, *x);
62+
63+
// Convert radians to degrees.
64+
*latDeg = latRad * (180.0 / PI);
65+
*lonDeg = lonRad * (180.0 / PI);
3766
}
3867

3968
int main(const int argc, const char** argv)
@@ -53,6 +82,7 @@ int main(const int argc, const char** argv)
5382
// Decode: [-d | --decode] <default-territory> <mapcode> [<mapcode> ...]
5483
// ------------------------------------------------------------------
5584
if (argc < 4) {
85+
printf("error: incorrect number of arguments\n\n");
5686
usage(appName);
5787
return -1;
5888
}
@@ -76,6 +106,7 @@ int main(const int argc, const char** argv)
76106
// Encode: [-e | --encode] <lat:-90..90> <lon:-180..180> [territory]>
77107
// ------------------------------------------------------------------
78108
if ((argc != 4) && (argc != 5)) {
109+
printf("error: incorrect number of arguments\n\n");
79110
usage(appName);
80111
return -1;
81112
}
@@ -96,45 +127,53 @@ int main(const int argc, const char** argv)
96127
printf("%s %s\n", results[(i * 2) + 1], results[(i * 2)]);
97128
}
98129
}
99-
else if ((strcmp(cmd, "-g") == 0) || (strcmp(cmd, "--generate") == 0)) {
130+
else if ((strcmp(cmd, "-g") == 0) || (strcmp(cmd, "--grid") == 0) ||
131+
(strcmp(cmd, "-r") == 0) || (strcmp(cmd, "--random") == 0)) {
100132

101133
// ------------------------------------------------------------------
102-
// Generate uniform test set: [-g | --generate] <nrPoints> [<seed>]
134+
// Generate grid test set: [-g | --grid] <nrPoints>
135+
// Generate uniform test set: [-r | --random] <nrPoints> [<seed>]
103136
// ------------------------------------------------------------------
104-
if ((argc != 3) && (argc != 4)) {
137+
if ((argc < 3) || (argc > 4)) {
138+
printf("error: incorrect number of arguments\n\n");
105139
usage(appName);
106140
return -1;
107141
}
108142
const int nrPoints = atoi(argv[2]);
109-
110-
if (argc == 4) {
111-
const int seed = atoi(argv[3]);
112-
srand(seed);
143+
int random = (strcmp(cmd, "-r") == 0) || (strcmp(cmd, "--random") == 0);
144+
if (random) {
145+
if (argc == 4) {
146+
const int seed = atoi(argv[3]);
147+
srand(seed);
148+
}
149+
else {
150+
srand(time(0));
151+
}
113152
}
114153
else {
115-
srand(time(0));
154+
if (argc > 3) {
155+
printf("error: cannot specify seed for -g/--grid\n\n");
156+
usage(appName);
157+
return -1;
158+
}
116159
}
160+
117161
const char* results[32];
118162
int context = 0;
119-
for (int i = 0; i < nrPoints; ++i) {
120163

121-
// Calculate uniformly distributed 3D point on sphere (radius = 1.0):
122-
// http://mathproofs.blogspot.co.il/2005/04/uniform-random-distribution-on-sphere.html
123-
const double unitRand = ((double) rand()) / RAND_MAX;
124-
const double theta0 = (2.0 * PI) * unitRand;
125-
const double theta1 = acos(1.0 - (2.0 * unitRand));
126-
const double x = sin(theta0) * sin(theta1);
127-
const double y = cos(theta0) * sin(theta1);
128-
const double z = cos(theta1);
164+
double walker = 0.0;
165+
const double increment = 1.0 / nrPoints;
166+
167+
for (int i = 0; i < nrPoints; ++i) {
129168

130-
// Convert Carthesian 3D point into lat/lon (radius = 1.0):
131-
// http://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates
132-
const double latRad = asin(z);
133-
const double lonRad = atan2(y, x);
169+
double lat;
170+
double lon;
171+
double x;
172+
double y;
173+
double z;
174+
double unit = (random ? (((double) rand()) / RAND_MAX) : walker);
134175

135-
// Convert radians to degrees.
136-
const double lat = latRad * (180.0 / PI);
137-
const double lon = lonRad * (180.0 / PI);
176+
unitToLatLonDegXYZ(unit, &lat, &lon, &x, &y, &z);
138177

139178
const int nrResults = coord2mc(results, lat, lon, context);
140179
if (nrResults <= 0) {
@@ -146,6 +185,7 @@ int main(const int argc, const char** argv)
146185
printf("%s %s\n", results[(i * 2) + 1], results[(i * 2)]);
147186
}
148187
printf("\n");
188+
walker += increment;
149189
}
150190
}
151191
else {

0 commit comments

Comments
 (0)