88#include "mapcoder/mapcoder.c"
99
1010static const double PI = 3.14159265358979323846 ;
11+ static const int RESULTS_MAX = 64 ;
1112
1213static void usage (const char * appName ) {
1314 printf ("Usage: \n" );
@@ -45,12 +46,13 @@ static void usage(const char* appName) {
4546 * (x, y, z) point on a sphere with a radius of 1.
4647 */
4748static void unitToLatLonDegXYZ (
48- const double unit , double * latDeg , double * lonDeg , double * x , double * y , double * z ) {
49+ const double unit1 , const double unit2 ,
50+ double * latDeg , double * lonDeg , double * x , double * y , double * z ) {
4951
5052 // Calculate uniformly distributed 3D point on sphere (radius = 1.0):
5153 // 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+ const double theta0 = (2.0 * PI ) * unit1 ;
55+ const double theta1 = acos (1.0 - (2.0 * unit2 ));
5456 * x = sin (theta0 ) * sin (theta1 );
5557 * y = cos (theta0 ) * sin (theta1 );
5658 * z = cos (theta1 );
@@ -61,8 +63,8 @@ static void unitToLatLonDegXYZ(
6163 const double lonRad = atan2 (* y , * x );
6264
6365 // Convert radians to degrees.
64- * latDeg = latRad * (180.0 / PI );
65- * lonDeg = lonRad * (180.0 / PI );
66+ * latDeg = isnan ( latRad ) ? 90.0 : ( latRad * (180.0 / PI ) );
67+ * lonDeg = isnan ( lonRad ) ? 180.0 : ( lonRad * (180.0 / PI ) );
6668}
6769
6870int main (const int argc , const char * * argv )
@@ -82,7 +84,7 @@ int main(const int argc, const char** argv)
8284 // Decode: [-d | --decode] <default-territory> <mapcode> [<mapcode> ...]
8385 // ------------------------------------------------------------------
8486 if (argc < 4 ) {
85- printf ( "error: incorrect number of arguments\n\n" );
87+ fprintf ( stderr , "error: incorrect number of arguments\n\n" );
8688 usage (appName );
8789 return -1 ;
8890 }
@@ -94,7 +96,7 @@ int main(const int argc, const char** argv)
9496 for (int i = 3 ; i < argc ; ++ i ) {
9597 int err = mc2coord (& lat , & lon , argv [i ], context );
9698 if (err != 0 ) {
97- printf ( "error: cannot decode '%s' (default territory='%s')\n" , argv [i ], argv [2 ]);
99+ fprintf ( stderr , "error: cannot decode '%s' (default territory='%s')\n" , argv [i ], argv [2 ]);
98100 return -1 ;
99101 }
100102 printf ("%f %f\n" , lat , lon );
@@ -106,7 +108,7 @@ int main(const int argc, const char** argv)
106108 // Encode: [-e | --encode] <lat:-90..90> <lon:-180..180> [territory]>
107109 // ------------------------------------------------------------------
108110 if ((argc != 4 ) && (argc != 5 )) {
109- printf ( "error: incorrect number of arguments\n\n" );
111+ fprintf ( stderr , "error: incorrect number of arguments\n\n" );
110112 usage (appName );
111113 return -1 ;
112114 }
@@ -117,10 +119,11 @@ int main(const int argc, const char** argv)
117119 if (argc == 5 ) {
118120 context = text2tc (argv [4 ], 0 );
119121 }
120- const char * results [32 ];
122+ const char * results [RESULTS_MAX ];
121123 const int nrResults = coord2mc (results , lat , lon , context );
122124 if (nrResults <= 0 ) {
123- printf ("error: cannot encode lat=%s, lon=%s (default territory=%d)\n" , argv [2 ], argv [3 ], context );
125+ fprintf (stderr , "error: cannot encode lat=%s, lon=%s (default territory=%d)\n" ,
126+ argv [2 ], argv [3 ], context );
124127 return -1 ;
125128 }
126129 for (int i = 0 ; i < nrResults ; ++ i ) {
@@ -135,7 +138,7 @@ int main(const int argc, const char** argv)
135138 // Generate uniform test set: [-r | --random] <nrPoints> [<seed>]
136139 // ------------------------------------------------------------------
137140 if ((argc < 3 ) || (argc > 4 )) {
138- printf ( "error: incorrect number of arguments\n\n" );
141+ fprintf ( stderr , "error: incorrect number of arguments\n\n" );
139142 usage (appName );
140143 return -1 ;
141144 }
@@ -152,40 +155,55 @@ int main(const int argc, const char** argv)
152155 }
153156 else {
154157 if (argc > 3 ) {
155- printf ( "error: cannot specify seed for -g/--grid\n\n" );
158+ fprintf ( stderr , "error: cannot specify seed for -g/--grid\n\n" );
156159 usage (appName );
157160 return -1 ;
158161 }
159162 }
160163
161- const char * results [32 ];
164+ const char * results [RESULTS_MAX ];
162165 int context = 0 ;
163166
164- double walker = 0. 0 ;
165- const double increment = 1.0 / nrPoints ;
166-
167+ int gridX = 0 ;
168+ int gridY = 0 ;
169+ int line = round ( sqrt ( nrPoints ));
167170 for (int i = 0 ; i < nrPoints ; ++ i ) {
168-
169171 double lat ;
170172 double lon ;
171173 double x ;
172174 double y ;
173175 double z ;
174- double unit = (random ? (((double ) rand ()) / RAND_MAX ) : walker );
176+ double unit1 ;
177+ double unit2 ;
178+
179+ if (random ) {
180+ unit1 = ((double ) rand ()) / RAND_MAX ;
181+ unit2 = ((double ) rand ()) / RAND_MAX ;
182+ }
183+ else {
184+ unit1 = ((double ) gridX ) / line ;
185+ unit2 = ((double ) gridY ) / line ;
175186
176- unitToLatLonDegXYZ (unit , & lat , & lon , & x , & y , & z );
187+ if (gridX < line ) {
188+ ++ gridX ;
189+ }
190+ else {
191+ gridX = 0 ;
192+ ++ gridY ;
193+ }
194+ }
177195
196+ unitToLatLonDegXYZ (unit1 , unit2 , & lat , & lon , & x , & y , & z );
178197 const int nrResults = coord2mc (results , lat , lon , context );
179198 if (nrResults <= 0 ) {
180- printf ( "error: cannot encode lat=%f, lon=%f)\n" , lat , lon );
199+ fprintf ( stderr , "error: cannot encode lat=%f, lon=%f)\n" , lat , lon );
181200 return -1 ;
182201 }
183202 printf ("%d %lf %lf %lf %lf %lf\n" , nrResults , lat , lon , x , y , z );
184- for (int i = 0 ; i < nrResults ; ++ i ) {
185- printf ("%s %s\n" , results [(i * 2 ) + 1 ], results [(i * 2 )]);
203+ for (int j = 0 ; j < nrResults ; ++ j ) {
204+ printf ("%s %s\n" , results [(j * 2 ) + 1 ], results [(j * 2 )]);
186205 }
187206 printf ("\n" );
188- walker += increment ;
189207 }
190208 }
191209 else {
@@ -198,3 +216,151 @@ int main(const int argc, const char** argv)
198216 }
199217 return 0 ;
200218}
219+
220+ /**
221+ * This program can encode and decode Mapcodes. It can also generate reference Mapcodes,
222+ * lat/lon pairs and their corresponding (x, y, z) coordinates.
223+ *
224+ * If you'd like to visualize the generated points, you can use "Processing" from
225+ * processing.org with the following Processing (Java) source code:
226+ *
227+
228+ ---------------------------------------------------------------------------
229+ // Visualize 3D points.
230+ //
231+ // Copyright (C) 2014, TomTom BV
232+ // Rijn Buve, 2014-08-24
233+
234+ final String DATA_FILE = "/Users/rijn/tmp/x";
235+
236+ final int N = 100000;
237+ final int C = 150;
238+ final int D = 1;
239+ final boolean DRAW_LAT_LON = true;
240+ final boolean STAR_SHAPE = true;
241+
242+ float posX;
243+ float posY;
244+ float posZ;
245+ float rotX = 1.2;
246+ float rotY = 0;
247+ float rotZ = 0.9;
248+
249+ float[] lat = new float[N];
250+ float[] lon = new float[N];
251+
252+ float[] px = new float[N];
253+ float[] py = new float[N];
254+ float[] pz = new float[N];
255+
256+ int total;
257+
258+ void setup() {
259+ size(650, 550, P3D);
260+ posX = width / 2.0;
261+ posY = height / 2.0;
262+ posZ = 0.0;
263+ total = 0;
264+ BufferedReader reader = createReader(DATA_FILE);
265+ try {
266+ while (true) {
267+ String line = reader.readLine();
268+ if (line == null) {
269+ break;
270+ }
271+
272+ // Parse line.
273+ String[] items = split(line, " ");
274+ int nrItems = Integer.parseInt(items[0]);
275+ lat[total] = Float.parseFloat(items[1]) / 90.0;
276+ lon[total] = Float.parseFloat(items[2]) / 180.0;
277+ px[total] = Float.parseFloat(items[3]);
278+ py[total] = Float.parseFloat(items[4]);
279+ pz[total] = Float.parseFloat(items[5]);
280+
281+ // Skip codes.
282+ for (int i = 0; i < nrItems; ++i) {
283+ reader.readLine();
284+ }
285+ reader.readLine();
286+ ++total;
287+ }
288+ }
289+ catch (IOException e) {
290+ e.printStackTrace();
291+ }
292+ finally {
293+ try {
294+ reader.close();
295+ }
296+ catch (IOException e) {
297+ // Ignored.
298+ }
299+ }
300+ }
301+
302+ void draw() {
303+ clear();
304+ translate(posX, posY, posZ);
305+ rotateX(rotX);
306+ rotateY(rotY);
307+ rotateZ(rotZ);
308+
309+ // Draw sphere.
310+ stroke(255, 0, 0, 50);
311+ fill(255, 0, 0, 50);
312+ sphere(C * 0.95);
313+ stroke(255, 0, 0, 255);
314+
315+ // Draw poles.
316+ line(0, 0, -C - 200, 0, 0, C + 200);
317+
318+ // Draw sphere dots.
319+ stroke(255, 255, 255, 200);
320+ for (int i = 0; i < total; ++i) {
321+ float x = C * px[i];
322+ float y = C * py[i];
323+ float z = C * pz[i];
324+ if (STAR_SHAPE) {
325+ line(x - D, y , z, x + D, y, z);
326+ line(x, y - D , z, x, y + D, z);
327+ }
328+ line(x, y , z - D, x, y, z + D);
329+ }
330+
331+ if (DRAW_LAT_LON) {
332+
333+ // Draw lat/lon bounds.
334+ stroke(0, 255, 255, 200);
335+ line(C + 5, -C - 50, C + 5, C + 5, -C - 50, -C - 5);
336+ line(C + 5, -C - 50, -C - 5, -C - 5, -C - 50, -C - 5);
337+ line(-C - 5, -C - 50, -C - 5, -C - 5, -C - 50, C + 5);
338+ line(-C - 5, -C - 50, C + 5, C + 5, -C - 50, C + 5);
339+
340+ // Draw lat/lon dots.
341+ stroke(255, 255, 0, 200);
342+ for (int i = 0; i < total; ++i) {
343+ float x = C * lon[i];
344+ float y = -C - 51;
345+ float z = C * lat[i];
346+ if (STAR_SHAPE) {
347+ line(x - D , y, z, x + D, y, z);
348+ line(x , y - D, z, x, y + D, z);
349+ }
350+ line(x , y, z - D, x, y, z + D);
351+ }
352+ }
353+
354+ if (mousePressed) {
355+ rotX += 0.01;
356+ rotY -= 0.0016;
357+ rotZ += 0.0043;
358+ }
359+ }
360+ ---------------------------------------------------------------------------
361+ *
362+ * Have fun!
363+ *
364+ * Rijn Buve, August 2014.
365+ */
366+
0 commit comments