mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-03 08:55:41 +02:00
Checkpoint work on spiral labels
This commit is contained in:
@@ -1800,6 +1800,84 @@ static bool line_is_too_small(drawvec const &geometry, int z, int detail) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static double dist(long long x1, long long y1, long long x2, long long y2) {
|
||||
double dx = x2 - x1;
|
||||
double dy = y2 - y1;
|
||||
return sqrt(dx * dx + dy * dy);
|
||||
}
|
||||
|
||||
drawvec spiral_anchors(drawvec const &geom, int tx, int ty, int z, unsigned long long label_point) {
|
||||
drawvec out;
|
||||
|
||||
// anchor point in world coordinates
|
||||
unsigned wx, wy;
|
||||
decode_index(label_point, &wx, &wy);
|
||||
printf("point %u,%u\n", wx, wy);
|
||||
|
||||
// upper left of tile in world coordinates
|
||||
long long tx1 = 0, ty1 = 0;
|
||||
// lower right of tile in world coordinates;
|
||||
long long tx2 = 1LL << 32, ty2 = 1LL << 32;
|
||||
if (z != 0) {
|
||||
tx1 = (long long) tx << (32 - z);
|
||||
ty1 = (long long) ty << (32 - z);
|
||||
|
||||
tx2 = (long long) (tx + 1) << (32 - z);
|
||||
ty2 = (long long) (ty + 1) << (32 - z);
|
||||
}
|
||||
printf("tile %lld,%lld to %lld,%lld\n", tx1, ty1, tx2, ty2);
|
||||
|
||||
// min and max distance of corners of this tile from the label point
|
||||
double min_radius, max_radius;
|
||||
if (wx >= tx1 && wx <= tx2 && wy >= ty1 && wy <= ty2) {
|
||||
// center is in this tile
|
||||
min_radius = 0;
|
||||
} else {
|
||||
// center is elsewhere
|
||||
min_radius = std::min(dist(wx, wy, tx1, ty1),
|
||||
std::min(dist(wx, wy, tx2, ty1),
|
||||
std::min(dist(wx, wy, tx2, ty2),
|
||||
dist(wx, wy, tx1, ty2))));
|
||||
}
|
||||
|
||||
max_radius = std::max(dist(wx, wy, tx1, ty1),
|
||||
std::max(dist(wx, wy, tx2, ty1),
|
||||
std::max(dist(wx, wy, tx2, ty2),
|
||||
dist(wx, wy, tx1, ty2))));
|
||||
|
||||
printf("radius (world) %f to %f\n", min_radius, max_radius);
|
||||
|
||||
// from world coordinates to tiles
|
||||
min_radius /= 1LL << (32 - z);
|
||||
max_radius /= 1LL << (32 - z);
|
||||
|
||||
printf("radius (tiles) %f to %f\n", min_radius, max_radius);
|
||||
|
||||
// labels complete a circle every 0.02 tiles of radius
|
||||
const double spiral_dist = 0.02;
|
||||
|
||||
size_t min_i = pow(min_radius / spiral_dist, 2);
|
||||
size_t max_i = pow(max_radius / spiral_dist, 2);
|
||||
|
||||
// https://craftofcoding.wordpress.com/tag/sunflower-spiral/
|
||||
double angle = M_PI * (3.0 - sqrt(5.0)); // 137.5 in radians
|
||||
|
||||
printf("making points %zu to %zu\n", min_i, max_i);
|
||||
for (size_t i = min_i; i <= max_i; i++) {
|
||||
double r = sqrt(i) * spiral_dist;
|
||||
double theta = i * angle;
|
||||
// Convert polar to cartesian
|
||||
long long x = r * cos(theta) * (1LL << (32 - z)) + wx;
|
||||
long long y = r * sin(theta) * (1LL << (32 - z)) + wy;
|
||||
|
||||
if (x >= tx1 && x <= tx2 && y >= ty1 && y <= ty2) {
|
||||
out.push_back(draw(VT_MOVETO, x - tx1, y - ty1));
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *metabase, char *stringpool, int z, const unsigned tx, const unsigned ty, const int detail, int min_detail, sqlite3 *outdb, const char *outdir, int buffer, const char *fname, FILE **geomfile, int minzoom, int maxzoom, double todo, std::atomic<long long> *along, long long alongminus, double gamma, int child_shards, long long *meta_off, long long *pool_off, unsigned *initial_x, unsigned *initial_y, std::atomic<int> *running, double simplification, std::vector<std::map<std::string, layermap_entry>> *layermaps, std::vector<std::vector<std::string>> *layer_unmaps, size_t tiling_seg, size_t pass, size_t passes, unsigned long long mingap, long long minextent, double fraction, const char *prefilter, const char *postfilter, struct json_object *filter, write_tile_args *arg, atomic_strategy *strategy) {
|
||||
double merge_fraction = 1;
|
||||
double mingap_fraction = 1;
|
||||
@@ -2085,27 +2163,8 @@ long long write_tile(FILE *geoms, std::atomic<long long> *geompos_in, char *meta
|
||||
}
|
||||
|
||||
if (sf.t == VT_POLYGON && additional[A_GENERATE_POLYGON_LABEL_POINTS]) {
|
||||
// Checkerboard which tiles labels are generated for this polygon in,
|
||||
// so we don't end up with multiple labels right next to each other.
|
||||
// There is a label in the tile that the polygon nominally belongs to,
|
||||
// and in other tiles reachable diagonally from there, but not in
|
||||
// the ones directly on either side.
|
||||
|
||||
unsigned wx, wy;
|
||||
decode_index(sf.index, &wx, &wy);
|
||||
|
||||
unsigned poly_tx = 0, poly_ty = 0;
|
||||
if (z != 0) {
|
||||
poly_tx = wx >> (32 - z);
|
||||
poly_ty = wy >> (32 - z);
|
||||
|
||||
if (((tx - poly_tx + ty - poly_ty) & 1) != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sf.t = VT_POINT;
|
||||
sf.geometry = polygon_to_anchor(sf.geometry);
|
||||
sf.geometry = spiral_anchors(sf.geometry, tx, ty, z, sf.label_point);
|
||||
}
|
||||
|
||||
if (sf.geometry.size() > 0) {
|
||||
|
||||
Reference in New Issue
Block a user