-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'clean-up-feature-dropping' into droprate
- Loading branch information
Showing
59 changed files
with
89,058 additions
and
66,735 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#include <cmath> | ||
#include "drop.hpp" | ||
#include "options.hpp" | ||
#include "geometry.hpp" | ||
|
||
unsigned long long preserve_point_density_threshold = 0; | ||
|
||
int calc_feature_minzoom(struct index *ix, struct drop_state ds[], int maxzoom, double gamma) { | ||
int feature_minzoom = 0; | ||
|
||
if (gamma >= 0 && (ix->t == VT_POINT || | ||
(additional[A_LINE_DROP] && ix->t == VT_LINE) || | ||
(additional[A_POLYGON_DROP] && ix->t == VT_POLYGON))) { | ||
for (ssize_t i = 0; i <= maxzoom; i++) { | ||
// This zoom level is now lighter on features | ||
ds[i].error -= 1.0; | ||
} | ||
|
||
ssize_t chosen = maxzoom + 1; | ||
for (ssize_t i = 0; i <= maxzoom; i++) { | ||
if (ds[i].error < 0) { | ||
// this zoom level is too light, so it is time to emit a feature. | ||
feature_minzoom = i; | ||
|
||
// this feature now appears in this zoom level and all higher zoom levels, | ||
// so each of them has this feature as its last feature, and each of them | ||
// is now one feature (which has a weight of `interval`) heavier than before. | ||
for (ssize_t j = i; j <= maxzoom; j++) { | ||
ds[j].previndex = ix->ix; | ||
ds[j].error += ds[j].interval; | ||
} | ||
|
||
chosen = i; | ||
break; | ||
} | ||
} | ||
|
||
// If this feature has been chosen only for a high zoom level, | ||
// check whether at a low zoom level it is nevertheless too far | ||
// from the last feature chosen for that low zoom, in which case | ||
// we will go ahead and push it out. | ||
|
||
if (preserve_point_density_threshold > 0) { | ||
for (ssize_t i = 0; i < chosen && i < maxzoom; i++) { | ||
if (ix->ix - ds[i].previndex > ((1LL << (32 - i)) / preserve_point_density_threshold) * ((1LL << (32 - i)) / preserve_point_density_threshold)) { | ||
feature_minzoom = i; | ||
|
||
// this feature now appears in this zoom level and all higher zoom levels | ||
// (below `chosen`, beyond which were already credited with this feature) | ||
// so each of them has this feature as its last feature, and each of them | ||
// is now one feature (which has a weight of `interval`) heavier than before. | ||
for (ssize_t j = i; j < chosen; j++) { | ||
ds[j].previndex = ix->ix; | ||
ds[j].error += ds[j].interval; | ||
} | ||
|
||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
return feature_minzoom; | ||
} | ||
|
||
void prep_drop_states(struct drop_state ds[], int maxzoom, int basezoom, double droprate) { | ||
// Needs to be signed for interval calculation | ||
for (ssize_t i = 0; i <= maxzoom; i++) { | ||
ds[i].previndex = 0; | ||
ds[i].interval = 1; // every feature appears in every zoom level at or above the basezoom | ||
|
||
if (i < basezoom) { | ||
// at zoom levels below the basezoom, the fraction of points that are dropped is | ||
// the drop rate to the power of the number of zooms this zoom is below the basezoom | ||
// | ||
// for example: | ||
// basezoom: 1 (droprate ^ 0) | ||
// basezoom - 1: 2.5 (droprate ^ 1) | ||
// basezoom - 2: 6.25 (droprate ^ 2) | ||
// ... | ||
// basezoom - n: (droprate ^ n) | ||
ds[i].interval = std::pow(droprate, basezoom - i); | ||
} | ||
|
||
ds[i].error = 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
#ifndef DROP_HPP | ||
#define DROP_HPP | ||
|
||
// As features are read during the input phase, each one is represented by | ||
// an index entry giving its geometry type, its spatial index, and the location | ||
// in the geometry file of the rest of its data. | ||
// | ||
// Note that the fields are in a specific order so that `segment` and `t` will | ||
// packed together with `seq` so that the total structure size will be only 32 bytes | ||
// instead of 40. (Could we save a few more, perhaps, by tracking `len` instead of | ||
// `end` and limiting the size of individual features to 2^32 bytes?) | ||
|
||
struct index { | ||
// first and last+1 byte of the feature in the geometry temp file | ||
long long start = 0; | ||
long long end = 0; | ||
|
||
// z-index or hilbert index of the feature | ||
unsigned long long ix = 0; | ||
|
||
// which thread's geometry temp file this feature is in | ||
short segment = 0; | ||
|
||
// geometry type | ||
unsigned short t : 2; | ||
|
||
// sequence number (sometimes with gaps in numbering) of the feature in the original input file | ||
unsigned long long seq : (64 - 16 - 2); // pack with segment and t to stay in 32 bytes | ||
|
||
index() | ||
: t(0), | ||
seq(0) { | ||
} | ||
}; | ||
|
||
// Each zoom level has a drop_state that is used to account for the fraction of | ||
// point features that are supposed to be dropped in that zoom level. As it goes | ||
// through the spatially-sorted features, it is basically doing a diffusion dither | ||
// to keep the density of features in each vicinity at each zoom level | ||
// approximately correct by including or excluding individual features | ||
// to maintain the balance. | ||
|
||
struct drop_state { | ||
// the z-index or hilbert index of the last feature that was placed in this zoom level | ||
unsigned long long previndex; | ||
|
||
// the preservation rate (1 or more) for features in this zoom level. | ||
// 1 would be to keep all the features; 2 would drop every other feature; | ||
// 4 every fourth feature, and so on. | ||
double interval; | ||
|
||
// the current accumulated error in this zoom level: | ||
// positive if too many features have been dropped; | ||
// negative if not enough features have been dropped. | ||
// | ||
// this is floating-point because the interval is. | ||
double error; | ||
}; | ||
|
||
extern unsigned long long preserve_point_density_threshold; | ||
|
||
int calc_feature_minzoom(struct index *ix, struct drop_state ds[], int maxzoom, double gamma); | ||
void prep_drop_states(struct drop_state ds[], int maxzoom, int basezoom, double droprate); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.