Skip to content

Commit 41c123c

Browse files
committed
Fixed major bug in transformation
1 parent 1fb9c03 commit 41c123c

File tree

1 file changed

+189
-23
lines changed

1 file changed

+189
-23
lines changed

mapcode.c

Lines changed: 189 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "mapcoder/mapcoder.c"
99

1010
static const double PI = 3.14159265358979323846;
11+
static const int RESULTS_MAX = 64;
1112

1213
static 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
*/
4748
static 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

6870
int 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

Comments
 (0)