void parse_geometry(int t, json_object *j, unsigned *bbox, long long *fpos, FILE *out, int op, const char *fname, json_pull *source) { if (j == NULL || j->type != JSON_ARRAY) { fprintf(stderr, "%s:%d: expected array for type %d\n", fname, source->line, t); return; } int within = geometry_within[t]; long long began = *fpos; if (within >= 0) { int i; for (i = 0; i < j->length; i++) { if (within == GEOM_POINT) { if (i == 0 || mb_geometry[t] == GEOM_MULTIPOINT) { op = VT_MOVETO; } else { op = VT_LINETO; } } parse_geometry(within, j->array[i], bbox, fpos, out, op, fname, source); } } else { if (j->length >= 2 && j->array[0]->type == JSON_NUMBER && j->array[1]->type == JSON_NUMBER) { unsigned x, y; double lon = j->array[0]->number; double lat = j->array[1]->number; latlon2tile(lat, lon, 32, &x, &y); if (j->length > 2) { static int warned = 0; if (!warned) { fprintf(stderr, "%s:%d: ignoring dimensions beyond two\n", fname, source->line); warned = 1; } } if (bbox != NULL) { if (x < bbox[0]) { bbox[0] = x; } if (y < bbox[1]) { bbox[1] = y; } if (x > bbox[2]) { bbox[2] = x; } if (y > bbox[3]) { bbox[3] = y; } } serialize_byte(out, op, fpos, fname); serialize_uint(out, x, fpos, fname); serialize_uint(out, y, fpos, fname); } else { fprintf(stderr, "%s:%d: malformed point\n", fname, source->line); } } if (t == GEOM_POLYGON) { if (*fpos != began) { serialize_byte(out, VT_CLOSEPATH, fpos, fname); } } }
void read_file(FILE *f, char *destdir, struct file **files, int *maxn) { char s[MAX_INPUT]; double lat[MAX_INPUT], lon[MAX_INPUT]; int metasize[MAX_INPUT]; long long meta[MAX_INPUT]; unsigned int x[MAX_INPUT], y[MAX_INPUT]; unsigned long long seq = 0; while (fgets(s, MAX_INPUT, f)) { char *cp = s; int n = 0, m = 0; if (seq % 100000 == 0) { fprintf(stderr, "Read %.1f million records\r", seq / 1000000.0); } seq++; while (1) { if (sscanf(cp, "%lf,%lf", &lat[n], &lon[n]) == 2) { n++; while (*cp != '\0' && *cp != ' ') { cp++; } while (*cp == ' ') { cp++; } } else if (sscanf(cp, "%d:%lld", &metasize[m], &meta[m]) == 2) { m++; while (*cp != '\0' && *cp != ' ') { cp++; } while (*cp == ' ') { cp++; } } else { break; } } // Project each point to web mercator int i; for (i = 0; i < n; i++) { if (lat[i] > 85.0511 || lat[i] < -85.0511) { fprintf(stderr, "Can't represent latitude %f\n", lat[i]); n = 0; break; } if (lon[i] >= 180 || lon[i] <= -180) { fprintf(stderr, "Can't represent longitude %f\n", lon[i]); n = 0; break; } latlon2tile(lat[i], lon[i], 32, &x[i], &y[i]); } if (n == 0) { fprintf(stderr, "No valid points in %s", s); continue; } // If this is a polyline, find out how many leading bits in common // all the points have. int common = 0; if (n > 1) { int ok = 1; for (common = 0; ok && common < mapbits / 2; common++) { int x0 = x[0] & (1 << (31 - common)); int y0 = y[0] & (1 << (31 - common)); for (i = 1; i < n; i++) { if ((x[i] & (1 << (31 - common))) != x0 || (y[i] & (1 << (31 - common))) != y0) { ok = 0; break; } } if (!ok) { break; } } } if (n > *maxn) { *maxn = n; } int bytes = bytesfor(mapbits, metabits, n, common); unsigned char buf[bytes]; memset(buf, 0, bytes); int off = 0; xy2buf(x[0], y[0], buf, &off, mapbits, 0); for (i = 1; i < n; i++) { xy2buf(x[i], y[i], buf, &off, mapbits, common); } for (i = 0; i < m; i++) { meta2buf(metasize[i], meta[i], buf, &off, bytes * 8); } struct file **fo; for (fo = files; *fo != NULL; fo = &((*fo)->next)) { if ((*fo)->legs == n && (*fo)->level == common) { break; } } if (*fo == NULL) { *fo = malloc(sizeof(struct file)); if (*fo == NULL) { perror("malloc"); exit(EXIT_FAILURE); } char fn[strlen(destdir) + 10 + 1 + 10 + 1]; sprintf(fn, "%s/%d,%d", destdir, n, common); (*fo)->legs = n; (*fo)->level = common; (*fo)->f = fopen(fn, "w"); if ((*fo)->f == NULL) { perror(fn); exit(EXIT_FAILURE); } } fwrite(buf, sizeof(char), bytes, (*fo)->f); } }