@@ -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
3968int 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