Start converting C arrays to C++ vectors

This commit is contained in:
Eric Fischer
2014-09-30 15:53:45 -07:00
parent 04c8a4441d
commit 1b3620dabc
+113 -120
View File
@@ -2,6 +2,8 @@
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <stack> #include <stack>
#include <vector>
#include <algorithm>
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <zlib.h> #include <zlib.h>
@@ -55,22 +57,20 @@ struct draw {
int necessary; int necessary;
}; };
int decode_feature(char **meta, struct draw *out, int z, unsigned tx, unsigned ty, int detail) { typedef std::vector<draw> drawvec;
int len = 0;
drawvec decode_feature(char **meta, int z, unsigned tx, unsigned ty, int detail) {
drawvec out;
while (1) { while (1) {
int op; draw d;
deserialize_int(meta, &op);
if (op == VT_END) { deserialize_int(meta, &d.op);
if (d.op == VT_END) {
break; break;
} }
if (out != NULL) { if (d.op == VT_MOVETO || d.op == VT_LINETO) {
out[len].op = op;
}
if (op == VT_MOVETO || op == VT_LINETO) {
int wx, wy; int wx, wy;
deserialize_int(meta, &wx); deserialize_int(meta, &wx);
deserialize_int(meta, &wy); deserialize_int(meta, &wy);
@@ -83,19 +83,17 @@ int decode_feature(char **meta, struct draw *out, int z, unsigned tx, unsigned t
wwy -= ty << (32 - z); wwy -= ty << (32 - z);
} }
if (out != NULL) { d.x = wwx;
out[len].x = wwx; d.y = wwy;
out[len].y = wwy;
}
} }
len++; out.push_back(d);
} }
return len; return out;
} }
int draw(struct draw *geom, int n, mapnik::vector::tile_feature *feature) { int draw(drawvec &geom, mapnik::vector::tile_feature *feature) {
int px = 0, py = 0; int px = 0, py = 0;
int cmd_idx = -1; int cmd_idx = -1;
int cmd = -1; int cmd = -1;
@@ -103,6 +101,7 @@ int draw(struct draw *geom, int n, mapnik::vector::tile_feature *feature) {
int drew = 0; int drew = 0;
int i; int i;
int n = geom.size();
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
int op = geom[i].op; int op = geom[i].op;
@@ -155,22 +154,22 @@ int draw(struct draw *geom, int n, mapnik::vector::tile_feature *feature) {
return drew; return drew;
} }
int remove_noop(struct draw *geom, int n, int type) { drawvec remove_noop(drawvec geom, int type) {
// first pass: remove empty linetos // first pass: remove empty linetos
long long x = 0, y = 0; long long x = 0, y = 0;
int out = 0; drawvec out;
int i; unsigned i;
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_LINETO && geom[i].x == x && geom[i].y == y) { if (geom[i].op == VT_LINETO && geom[i].x == x && geom[i].y == y) {
continue; continue;
} }
if (geom[i].op == VT_CLOSEPATH) { if (geom[i].op == VT_CLOSEPATH) {
geom[out++] = geom[i]; out.push_back(geom[i]);
} else { /* moveto or lineto */ } else { /* moveto or lineto */
geom[out++] = geom[i]; out.push_back(geom[i]);
x = geom[i].x; x = geom[i].x;
y = geom[i].y; y = geom[i].y;
} }
@@ -178,12 +177,12 @@ int remove_noop(struct draw *geom, int n, int type) {
// second pass: remove unused movetos // second pass: remove unused movetos
n = out; geom = out;
out = 0; out.resize(0);
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) { if (geom[i].op == VT_MOVETO) {
if (i + 1 >= n) { if (i + 1 >= geom.size()) {
continue; continue;
} }
@@ -197,23 +196,23 @@ int remove_noop(struct draw *geom, int n, int type) {
} }
} }
geom[out++] = geom[i]; out.push_back(geom[i]);
} }
// second pass: remove empty movetos // second pass: remove empty movetos
if (type == VT_LINE) { if (type == VT_LINE) {
n = out; geom = out;
out = 0; out.resize(0);
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) { if (geom[i].op == VT_MOVETO) {
if (i - 1 >= 0 && geom[i - 1].op == VT_LINETO && geom[i - 1].x == geom[i].x && geom[i - 1].y == geom[i].y) { if (i > 0 && geom[i - 1].op == VT_LINETO && geom[i - 1].x == geom[i].x && geom[i - 1].y == geom[i].y) {
continue; continue;
} }
} }
geom[out++] = geom[i]; out.push_back(geom[i]);
} }
} }
@@ -253,10 +252,10 @@ int shrink_lines(struct draw *geom, int len, int z, int basezoom) {
return out; return out;
} }
void to_tile_scale(struct draw *geom, int n, int z, int detail) { void to_tile_scale(drawvec &geom, int z, int detail) {
int i; unsigned i;
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
geom[i].x >>= (32 - detail - z); geom[i].x >>= (32 - detail - z);
geom[i].y >>= (32 - detail - z); geom[i].y >>= (32 - detail - z);
} }
@@ -284,7 +283,7 @@ double square_distance_from_line(long long point_x, long long point_y, long long
} }
// https://github.com/Project-OSRM/osrm-backend/blob/733d1384a40f/Algorithms/DouglasePeucker.cpp // https://github.com/Project-OSRM/osrm-backend/blob/733d1384a40f/Algorithms/DouglasePeucker.cpp
void douglas_peucker(struct draw *geom, int n, double e) { void douglas_peucker(drawvec &geom, int start, int n, double e) {
e = e * e; e = e * e;
std::stack<int> recursion_stack; std::stack<int> recursion_stack;
@@ -293,7 +292,7 @@ void douglas_peucker(struct draw *geom, int n, double e) {
int right_border = 1; int right_border = 1;
// Sweep linerarily over array and identify those ranges that need to be checked // Sweep linerarily over array and identify those ranges that need to be checked
do { do {
if (geom[right_border].necessary) { if (geom[start + right_border].necessary) {
recursion_stack.push(left_border); recursion_stack.push(left_border);
recursion_stack.push(right_border); recursion_stack.push(right_border);
left_border = right_border; left_border = right_border;
@@ -315,9 +314,9 @@ void douglas_peucker(struct draw *geom, int n, double e) {
// find index idx of element with max_distance // find index idx of element with max_distance
int i; int i;
for (i = first + 1; i < second; i++) { for (i = first + 1; i < second; i++) {
double temp_dist = square_distance_from_line(geom[i].x, geom[i].y, double temp_dist = square_distance_from_line(geom[start + i].x, geom[start + i].y,
geom[first].x, geom[first].y, geom[start + first].x, geom[start + first].y,
geom[second].x, geom[second].y); geom[start + second].x, geom[start + second].y);
double distance = fabs(temp_dist); double distance = fabs(temp_dist);
@@ -329,7 +328,7 @@ void douglas_peucker(struct draw *geom, int n, double e) {
if (max_distance > e) { if (max_distance > e) {
// mark idx as necessary // mark idx as necessary
geom[farthest_element_index].necessary = 1; geom[start + farthest_element_index].necessary = 1;
if (1 < farthest_element_index - first) { if (1 < farthest_element_index - first) {
recursion_stack.push(first); recursion_stack.push(first);
@@ -343,13 +342,12 @@ void douglas_peucker(struct draw *geom, int n, double e) {
} }
} }
int clip_lines(struct draw *geom, int n, int z, int detail) { drawvec clip_lines(drawvec &geom, int z, int detail) {
struct draw tmp[n * 3]; drawvec out;
int out = 0; unsigned i;
int i;
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
if (i - 1 >= 0 && (geom[i - 1].op == VT_MOVETO || geom[i - 1].op == VT_LINETO) && geom[i].op == VT_LINETO) { if (i > 0 && (geom[i - 1].op == VT_MOVETO || geom[i - 1].op == VT_LINETO) && geom[i].op == VT_LINETO) {
double x1 = geom[i - 1].x; double x1 = geom[i - 1].x;
double y1 = geom[i - 1].y; double y1 = geom[i - 1].y;
@@ -364,42 +362,45 @@ int clip_lines(struct draw *geom, int n, int z, int detail) {
int c = clip(&x1, &y1, &x2, &y2, 0, 0, area, area); int c = clip(&x1, &y1, &x2, &y2, 0, 0, area, area);
if (c > 1) { // clipped if (c > 1) { // clipped
tmp[out].op = VT_MOVETO; struct draw d;
tmp[out].x = x1;
tmp[out].y = y1;
out++;
tmp[out].op = VT_LINETO; d.op = VT_MOVETO;
tmp[out].x = x2; d.x = x1;
tmp[out].y = y2; d.y = y1;
out++; out.push_back(d);
d.op = VT_LINETO;
d.x = x2;
d.y = y2;
out.push_back(d);
tmp[out].op = VT_MOVETO; d.op = VT_MOVETO;
tmp[out].x = geom[i].x; d.x = geom[i].x;
tmp[out].y = geom[i].y; d.y = geom[i].y;
out++; out.push_back(d);
} else if (c == 1) { // unchanged } else if (c == 1) { // unchanged
tmp[out++] = geom[i]; out.push_back(geom[i]);
} else { // clipped away entirely } else { // clipped away entirely
tmp[out].op = VT_MOVETO; struct draw d;
tmp[out].op = geom[i].x;
tmp[out].op = geom[i].y; d.op = VT_MOVETO;
out++; d.op = geom[i].x;
d.op = geom[i].y;
out.push_back(d);
} }
} else { } else {
tmp[out++] = geom[i]; out.push_back(geom[i]);
} }
} }
memcpy(geom, tmp, out * sizeof(struct draw));
return out; return out;
} }
int simplify_lines(struct draw *geom, int n, int z, int detail) { drawvec simplify_lines(drawvec &geom, int z, int detail) {
int res = 1 << (32 - detail - z); int res = 1 << (32 - detail - z);
int i; unsigned i;
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) { if (geom[i].op == VT_MOVETO) {
geom[i].necessary = 1; geom[i].necessary = 1;
} else if (geom[i].op == VT_LINETO) { } else if (geom[i].op == VT_LINETO) {
@@ -409,10 +410,10 @@ int simplify_lines(struct draw *geom, int n, int z, int detail) {
} }
} }
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
if (geom[i].op == VT_MOVETO) { if (geom[i].op == VT_MOVETO) {
int j; unsigned j;
for (j = i + 1; j < n; j++) { for (j = i + 1; j < geom.size(); j++) {
if (geom[j].op == VT_CLOSEPATH || geom[j].op == VT_MOVETO) { if (geom[j].op == VT_CLOSEPATH || geom[j].op == VT_MOVETO) {
break; break;
} }
@@ -421,15 +422,15 @@ int simplify_lines(struct draw *geom, int n, int z, int detail) {
geom[i].necessary = 1; geom[i].necessary = 1;
geom[j - 1].necessary = 1; geom[j - 1].necessary = 1;
douglas_peucker(geom + i, j - i, res); douglas_peucker(geom, i, j - i, res);
i = j - 1; i = j - 1;
} }
} }
int out = 0; drawvec out;
for (i = 0; i < n; i++) { for (i = 0; i < geom.size(); i++) {
if (geom[i].necessary) { if (geom[i].necessary) {
geom[out++] = geom[i]; out.push_back(geom[i]);
} }
} }
@@ -440,7 +441,7 @@ struct coalesce {
int type; int type;
int ngeom; int ngeom;
struct draw *geom; drawvec geom;
int nmeta; int nmeta;
int *meta; int *meta;
@@ -510,8 +511,7 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns
interval = exp(log(2.5) * (basezoom - z)); interval = exp(log(2.5) * (basezoom - z));
} }
int nfeatures = 0; std::vector<coalesce> features;
struct coalesce *features = (struct coalesce *) malloc((end - start) * sizeof(struct coalesce));
struct index *i; struct index *i;
for (i = start; i < end; i++) { for (i = start; i < end; i++) {
@@ -530,19 +530,14 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns
} }
} }
int len = decode_feature(&meta, NULL, z, tx, ty, detail); drawvec geom = decode_feature(&meta, z, tx, ty, detail);
struct draw geom[3 * len];
meta = metabase + i->fpos;
deserialize_int(&meta, &t);
decode_feature(&meta, geom, z, tx, ty, detail);
if (t == VT_LINE) { if (t == VT_LINE) {
len = clip_lines(geom, len, z, detail); geom = clip_lines(geom, z, detail);
} }
if (t == VT_LINE || t == VT_POLYGON) { if (t == VT_LINE || t == VT_POLYGON) {
len = simplify_lines(geom, len, z, detail); geom = simplify_lines(geom, z, detail);
} }
#if 0 #if 0
@@ -551,27 +546,26 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns
} }
#endif #endif
to_tile_scale(geom, len, z, detail); to_tile_scale(geom, z, detail);
if (t == VT_POINT || draw(geom, len, NULL)) { if (t == VT_POINT || draw(geom, NULL)) {
struct pool_val *pv = pool_long_long(&dup, &i->fpos, 0); struct pool_val *pv = pool_long_long(&dup, &i->fpos, 0);
if (pv->n == 0) { if (pv->n == 0) {
continue; continue;
} }
pv->n = 0; pv->n = 0;
features[nfeatures].type = t; struct coalesce c;
features[nfeatures].index = i->index;
features[nfeatures].ngeom = len; c.type = t;
features[nfeatures].geom = (struct draw *) malloc(len * sizeof(struct draw)); c.index = i->index;
memcpy(features[nfeatures].geom, geom, len * sizeof(struct draw)); c.geom = geom;
int m; int m;
deserialize_int(&meta, &m); deserialize_int(&meta, &m);
features[nfeatures].nmeta = 2 * m; c.nmeta = 2 * m;
features[nfeatures].meta = (int *) malloc(2 * m * sizeof(int)); c.meta = (int *) malloc(2 * m * sizeof(int));
int i; int i;
for (i = 0; i < m; i++) { for (i = 0; i < m; i++) {
@@ -580,42 +574,42 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns
struct pool_val *key = deserialize_string(&meta, &keys, VT_STRING); struct pool_val *key = deserialize_string(&meta, &keys, VT_STRING);
struct pool_val *value = deserialize_string(&meta, &values, t); struct pool_val *value = deserialize_string(&meta, &values, t);
features[nfeatures].meta[2 * i + 0] = key->n; c.meta[2 * i + 0] = key->n;
features[nfeatures].meta[2 * i + 1] = value->n; c.meta[2 * i + 1] = value->n;
// Dup to retain after munmap // Dup to retain after munmap
pool(file_keys, strdup(key->s), t); pool(file_keys, strdup(key->s), t);
} }
nfeatures++; features.push_back(c);
} }
} }
qsort(features, nfeatures, sizeof(struct coalesce), coalindexcmp); // XXX
int x; // qsort(features, nfeatures, sizeof(struct coalesce), coalindexcmp);
int out = 0; std::vector<coalesce> out;
for (x = 0; x < nfeatures; x++) {
if (out > 0 && features[out - 1].ngeom + features[x].ngeom < 20000 && coalcmp(&features[x], &features[out - 1]) == 0 && features[x].type != VT_POINT) { unsigned x;
struct draw *tmp = (struct draw *) malloc((features[x].ngeom + features[out - 1].ngeom) * sizeof(struct draw)); for (x = 0; x < features.size(); x++) {
memcpy(tmp, features[out - 1].geom, features[out - 1].ngeom * sizeof(struct draw)); unsigned y = out.size() - 1;
memcpy(tmp + features[out - 1].ngeom, features[x].geom, features[x].ngeom * sizeof(struct draw));
if (out.size() > 0 && out[y].geom.size() + features[x].geom.size() < 20000 && coalcmp(&features[x], &out[y]) == 0 && features[x].type != VT_POINT) {
unsigned z;
for (z = 0; z < features[x].geom.size(); z++) {
out[y].geom.push_back(features[x].geom[z]);
}
free(features[x].geom);
free(features[out - 1].geom);
free(features[x].meta); free(features[x].meta);
features[out - 1].ngeom += features[x].ngeom;
features[out - 1].geom = tmp;
} else { } else {
features[out++] = features[x]; out.push_back(features[x]);
} }
} }
nfeatures = out;
for (x = 0; x < nfeatures; x++) { features = out;
for (x = 0; x < features.size(); x++) {
if (features[x].type == VT_LINE || features[x].type == VT_POLYGON) { if (features[x].type == VT_LINE || features[x].type == VT_POLYGON) {
features[x].ngeom = remove_noop(features[x].geom, features[x].ngeom, features[x].type); features[x].geom = remove_noop(features[x].geom, features[x].type);
} }
mapnik::vector::tile_feature *feature = layer->add_features(); mapnik::vector::tile_feature *feature = layer->add_features();
@@ -630,7 +624,7 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns
feature->set_type(mapnik::vector::tile::Unknown); feature->set_type(mapnik::vector::tile::Unknown);
} }
draw(features[x].geom, features[x].ngeom, feature); draw(features[x].geom, feature);
count += features[x].ngeom; count += features[x].ngeom;
int y; int y;
@@ -638,11 +632,10 @@ long long write_tile(struct index *start, struct index *end, char *metabase, uns
feature->add_tags(features[x].meta[y]); feature->add_tags(features[x].meta[y]);
} }
free(features[x].geom);
free(features[x].meta); free(features[x].meta);
} }
free(features); features.resize(0);
struct pool_val *pv; struct pool_val *pv;
for (pv = keys.head; pv != NULL; pv = pv->next) { for (pv = keys.head; pv != NULL; pv = pv->next) {