diff --git a/tile.cc b/tile.cc index 600922e..8cf286d 100644 --- a/tile.cc +++ b/tile.cc @@ -465,6 +465,92 @@ void rewrite(drawvec &geom, int z, int nextzoom, int maxzoom, long long *bbox, u } } +struct partial { + drawvec geom; + long long layer; + char *meta; + signed char t; + int segment; + long long original_seq; + bool reduced; + unsigned long long index; + unsigned long long index2; + int z; + int line_detail; + char *prevent; + char *additional; +}; + +struct partial_arg { + std::vector *partials; + int task; + int tasks; +}; + +void *partial_feature_worker(void *v) { + struct partial_arg *a = (struct partial_arg *) v; + std::vector *partials = a->partials; + + for (unsigned i = a->task; i < (*partials).size(); i += a->tasks) { + drawvec geom = (*partials)[i].geom; + (*partials)[i].geom.clear(); // avoid keeping two copies in memory + signed char t = (*partials)[i].t; + int z = (*partials)[i].z; + int line_detail = (*partials)[i].line_detail; + char *prevent = (*partials)[i].prevent; + char *additional = (*partials)[i].additional; + + if ((t == VT_LINE || t == VT_POLYGON) && !prevent['s' & 0xFF]) { + if (1 /* !reduced */) { // XXX why did this not simplify if reduced? + if (t == VT_LINE) { + geom = remove_noop(geom, t, 32 - z - line_detail); + } + + geom = simplify_lines(geom, z, line_detail); + } + } + +#if 0 + if (t == VT_LINE && z != basezoom) { + geom = shrink_lines(geom, z, line_detail, basezoom, &along); + } +#endif + + if (t == VT_LINE && additional['r' & 0xFF]) { + geom = reorder_lines(geom); + } + + to_tile_scale(geom, z, line_detail); + + if (t == VT_POLYGON) { + // Scaling may have made the polygon degenerate. + // Give Clipper a chance to try to fix it. + geom = clean_or_clip_poly(geom, 0, 0, 0, false); + geom = close_poly(geom); + } + + // Worth skipping this if not coalescing anyway? + if (geom.size() > 0) { + (*partials)[i].index = encode(geom[0].x, geom[0].y); + (*partials)[i].index2 = encode(geom[geom.size() - 1].x, geom[geom.size() - 1].y); + + // Anything numbered below the start of the line + // can't possibly be the next feature. + // We want lowest-but-not-under. + if ((*partials)[i].index2 < (*partials)[i].index) { + (*partials)[i].index2 = ~0LL; + } + } else { + (*partials)[i].index = 0; + (*partials)[i].index2 = 0; + } + + (*partials)[i].geom = geom; + } + + return NULL; +} + long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsigned tx, unsigned ty, int detail, int min_detail, int basezoom, struct pool **file_keys, char **layernames, sqlite3 *outdb, double droprate, int buffer, const char *fname, FILE **geomfile, int minzoom, int maxzoom, double todo, char *geomstart, volatile long long *along, double gamma, int nlayers, char *prevent, char *additional, int child_shards, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y) { int line_detail; double fraction = 1; @@ -523,6 +609,7 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsi long long original_features = 0; long long unclipped_features = 0; + std::vector partials; std::vector > features; for (i = 0; i < nlayers; i++) { features.push_back(std::vector()); @@ -621,7 +708,7 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsi geom = clip_lines(geom, z, line_detail, buffer); } if (t == VT_POLYGON) { - geom = clean_or_clip_poly(geom, z, line_detail, buffer, true); + geom = simple_clip_poly(geom, z, line_detail, buffer); } if (t == VT_POINT) { geom = clip_point(geom, z, line_detail, buffer); @@ -706,53 +793,71 @@ long long write_tile(char **geoms, char *metabase, char *stringpool, int z, unsi geom = reduce_tiny_poly(geom, z, line_detail, &reduced, &accum_area); } - if ((t == VT_LINE || t == VT_POLYGON) && !prevent['s' & 0xFF]) { - if (!reduced) { - if (t == VT_LINE) { - geom = remove_noop(geom, t, 32 - z - line_detail); - } + if (geom.size() > 0) { + partial p; + p.geom = geom; + p.layer = layer; + p.meta = meta; + p.t = t; + p.segment = segment; + p.original_seq = original_seq; + p.reduced = reduced; + p.z = z; + p.line_detail = line_detail; + p.prevent = prevent; + p.additional = additional; + partials.push_back(p); + } + } - geom = simplify_lines(geom, z, line_detail); + int tasks = CPUS / (1 << z); + if (tasks < 1) { + tasks = 1; + } + + pthread_t pthreads[tasks]; + partial_arg args[tasks]; + for (int i = 0; i < tasks; i++) { + args[i].task = i; + args[i].tasks = tasks; + args[i].partials = &partials; + + if (tasks > 1) { + if (pthread_create(&pthreads[i], NULL, partial_feature_worker, &args[i]) != 0) { + perror("pthread_create"); + exit(EXIT_FAILURE); + } + } else { + partial_feature_worker(&args[i]); + } + } + + if (tasks > 1) { + for (int i = 0; i < tasks; i++) { + void *retval; + + if (pthread_join(pthreads[i], &retval) != 0) { + perror("pthread_join"); } } + } -#if 0 - if (t == VT_LINE && z != basezoom) { - geom = shrink_lines(geom, z, line_detail, basezoom, &along); - } -#endif - - if (t == VT_LINE && additional['r' & 0xFF]) { - geom = reorder_lines(geom); - } - - to_tile_scale(geom, z, line_detail); - - if (t == VT_POLYGON) { - // Scaling may have made the polygon degenerate. - // Give Clipper a chance to try to fix it. - geom = clean_or_clip_poly(geom, 0, 0, 0, false); - geom = close_poly(geom); - } + // This is serial because decode_meta() unifies duplicates + for (unsigned i = 0; i < partials.size(); i++) { + drawvec geom = partials[i].geom; + partials[i].geom.clear(); // avoid keeping two copies in memory + long long layer = partials[i].layer; + char *meta = partials[i].meta; + signed char t = partials[i].t; + int segment = partials[i].segment; + long long original_seq = partials[i].original_seq; if (t == VT_POINT || to_feature(geom, NULL)) { struct coalesce c; c.type = t; - if (geom.size() > 0) { - c.index = encode(geom[0].x, geom[0].y); - c.index2 = encode(geom[geom.size() - 1].x, geom[geom.size() - 1].y); - - // Anything numbered below the start of the line - // can't possibly be the next feature. - // We want lowest-but-not-under. - if (c.index2 < c.index) { - c.index2 = ~0LL; - } - } else { - c.index = 0; - c.index2 = 0; - } + c.index = partials[i].index; + c.index2 = partials[i].index2; c.geom = geom; c.metasrc = meta; c.coalesced = false;