Skip to content

Commit

Permalink
Merge 5fc44ca into a6a8c24
Browse files Browse the repository at this point in the history
  • Loading branch information
msbarry authored Jul 26, 2022
2 parents a6a8c24 + 5fc44ca commit 3e1bf08
Show file tree
Hide file tree
Showing 9 changed files with 321 additions and 165 deletions.
11 changes: 6 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ To set up your local development environment:
- Install Java 16 or later. You can download Java manually from [Adoptium](https://adoptium.net/installation.html) or
use:
- [Windows installer](https://adoptium.net/installation.html#windows-msi)
- [macOS installer](https://adoptium.net/installation.html#macos-pkg) (or `brew install --cask temurin`, or `port install openjdk17-temurin`)
- [macOS installer](https://adoptium.net/installation.html#macos-pkg) (or `brew install --cask temurin`,
or `port install openjdk17-temurin`)
- [Linux installer](https://github.com/adoptium/website-v2/blob/main/src/asciidoc-pages/installation/linux.adoc)
(or `apt-get install openjdk-17-jdk`)
- Build and run the tests ([mvnw](https://github.com/takari/maven-wrapper) automatically downloads maven the first time
Expand All @@ -25,10 +26,10 @@ To set up your local development environment:
- to run just one test e.g. `GeoUtilsTest`: `./mvnw -pl planetiler-core -Dtest=GeoUtilsTest test`
- to run benchmarks e.g. `BenchmarkTileCoord`:

```sh
./scripts/build.sh
java -cp planetiler-dist/target/planetiler-dist-*-with-deps.jar com.onthegomap.planetiler.benchmarks.BenchmarkTileCoord
```
```sh
./scripts/build.sh
java -cp planetiler-dist/target/planetiler-dist-*-with-deps.jar com.onthegomap.planetiler.benchmarks.BenchmarkTileCoord
```

GitHub Workflows will run regression tests on any pull request.

Expand Down
2 changes: 2 additions & 0 deletions NOTICE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ The `planetiler-core` module includes the following software:
- `PbfFieldDecoder` from [osmosis](https://github.com/openstreetmap/osmosis) (Public Domain)
- `Madvise` from [uppend](https://github.com/upserve/uppend/) (MIT License)
- `ArrayLongMinHeap` implementations from [graphhopper](https://github.com/graphhopper/graphhopper) (Apache license)
- `Hilbert` implementation
from [github.com/rawrunprotected/hilbert_curves](https://github.com/rawrunprotected/hilbert_curves) (Public Domain)

Additionally, the `planetiler-basemap` module is based on [OpenMapTiles](https://github.com/openmaptiles/openmaptiles):

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public record PlanetilerConfig(
) {

public static final int MIN_MINZOOM = 0;
public static final int MAX_MAXZOOM = 14;
public static final int MAX_MAXZOOM = 15;
private static final int DEFAULT_MAXZOOM = 14;

public PlanetilerConfig {
if (minzoom > maxzoom) {
Expand Down Expand Up @@ -104,6 +105,12 @@ public static PlanetilerConfig from(Arguments arguments) {
throw new UncheckedIOException(e);
}
}

int minzoom = arguments.getInteger("minzoom", "minimum zoom level", MIN_MINZOOM);
int maxzoom = arguments.getInteger("maxzoom", "maximum zoom level up to " + MAX_MAXZOOM, DEFAULT_MAXZOOM);
int renderMaxzoom =
arguments.getInteger("render_maxzoom", "maximum rendering zoom level up to " + MAX_MAXZOOM,
Math.max(maxzoom, DEFAULT_MAXZOOM));
return new PlanetilerConfig(
arguments,
bounds,
Expand All @@ -113,9 +120,9 @@ public static PlanetilerConfig from(Arguments arguments) {
arguments.getInteger("feature_read_threads", "number of threads to use when reading features at tile write time",
threads < 32 ? 1 : 2),
arguments.getDuration("loginterval", "time between logs", "10s"),
arguments.getInteger("minzoom", "minimum zoom level", MIN_MINZOOM),
arguments.getInteger("maxzoom", "maximum zoom level (limit 14)", MAX_MAXZOOM),
arguments.getInteger("render_maxzoom", "maximum rendering zoom level (limit 14)", MAX_MAXZOOM),
minzoom,
maxzoom,
renderMaxzoom,
arguments.getBoolean("skip_mbtiles_index_creation", "skip adding index to mbtiles file", false),
arguments.getBoolean("optimize_db", "optimize mbtiles after writing", false),
arguments.getBoolean("emit_tiles_in_order", "emit tiles in index order", true),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.onthegomap.planetiler.geo;

import static com.onthegomap.planetiler.config.PlanetilerConfig.MAX_MAXZOOM;

import com.onthegomap.planetiler.util.Format;
import javax.annotation.concurrent.Immutable;
import org.locationtech.jts.geom.Coordinate;
Expand All @@ -21,28 +23,46 @@
*/
@Immutable
public record TileCoord(int encoded, int x, int y, int z) implements Comparable<TileCoord> {

private static final int[] ZOOM_START_INDEX = new int[MAX_MAXZOOM + 1];

static {
int idx = 0;
for (int z = 0; z <= MAX_MAXZOOM; z++) {
ZOOM_START_INDEX[z] = idx;
int count = (1 << z) * (1 << z);
if (Integer.MAX_VALUE - idx < count) {
throw new IllegalStateException("Too many zoom levels " + MAX_MAXZOOM);
}
idx += count;
}
}

private static int startIndexForZoom(int z) {
return ZOOM_START_INDEX[z];
}

private static int zoomForIndex(int idx) {
for (int z = MAX_MAXZOOM; z >= 0; z--) {
if (ZOOM_START_INDEX[z] <= idx) {
return z;
}
}
throw new IllegalArgumentException("Bad index: " + idx);
}

public TileCoord {
assert z <= 15;
assert z <= MAX_MAXZOOM;
}

public static TileCoord ofXYZ(int x, int y, int z) {
return new TileCoord(encode(x, y, z), x, y, z);
}

public static TileCoord decode(int encoded) {
int acc = 0;
int tmpZ = 0;
while (true) {
int numTiles = (1 << tmpZ) * (1 << tmpZ);
if (acc + numTiles > encoded) {
int position = encoded - acc;
// long xy = hilbertPositionToXY(tmpZ, position);
long xy = tmsPositionToXY(tmpZ, position);
return new TileCoord(encoded, (int) (xy >>> 32 & 0xFFFFFFFFL), (int) (xy & 0xFFFFFFFFL), tmpZ);
}
acc += numTiles;
tmpZ++;
}
int z = zoomForIndex(encoded);
long xy = tmsPositionToXY(z, encoded - startIndexForZoom(z));
return new TileCoord(encoded, (int) (xy >>> 32 & 0xFFFFFFFFL), (int) (xy & 0xFFFFFFFFL), z);
}

/** Returns the tile containing a latitude/longitude coordinate at a given zoom level. */
Expand All @@ -54,12 +74,7 @@ public static TileCoord aroundLngLat(double lng, double lat, int zoom) {
}

public static int encode(int x, int y, int z) {
int acc = 0;
for (int tmpZ = 0; tmpZ < z; tmpZ++) {
acc += (1 << tmpZ) * (1 << tmpZ);
}
// return acc + hilbertXYToPosition(z, x, y);
return acc + tmsXYToPosition(z, x, y);
return startIndexForZoom(z) + tmsXYToPosition(z, x, y);
}

@Override
Expand All @@ -86,17 +101,11 @@ public String toString() {
return "{x=" + x + " y=" + y + " z=" + z + '}';
}

public double progressOnLevel() {
int acc = 0;
int tmpZ = 0;
while (true) {
int numTiles = (1 << tmpZ) * (1 << tmpZ);
if (acc + numTiles > encoded) {
return (encoded - acc) / (double) numTiles;
}
acc += numTiles;
tmpZ++;
}
public double progressOnLevel(TileExtents extents) {
// approximate percent complete within a bounding box by computing what % of the way through the columns we are
// (for hilbert ordering, we probably won't be able to reflect the bounding box)
var zoomBounds = extents.getForZoom(z);
return 1d * (x - zoomBounds.minX()) / (zoomBounds.maxX() - zoomBounds.minX());
}

@Override
Expand Down Expand Up @@ -141,107 +150,4 @@ public static int tmsXYToPosition(int z, int x, int y) {
int dim = 1 << z;
return x * dim + (dim - 1 - y);
}

// hilbert implementation (not currently used)
// Fast Hilbert curve algorithm by http://threadlocalmutex.com/
// Ported from C++ https://github.com/rawrunprotected/hilbert_curves (public domain)
private static int deinterleave(int tx) {
tx = tx & 0x55555555;
tx = (tx | (tx >>> 1)) & 0x33333333;
tx = (tx | (tx >>> 2)) & 0x0F0F0F0F;
tx = (tx | (tx >>> 4)) & 0x00FF00FF;
tx = (tx | (tx >>> 8)) & 0x0000FFFF;
return tx;
}

private static int interleave(int tx) {
tx = (tx | (tx << 8)) & 0x00FF00FF;
tx = (tx | (tx << 4)) & 0x0F0F0F0F;
tx = (tx | (tx << 2)) & 0x33333333;
tx = (tx | (tx << 1)) & 0x55555555;
return tx;
}

private static int prefixScan(int tx) {
tx = (tx >>> 8) ^ tx;
tx = (tx >>> 4) ^ tx;
tx = (tx >>> 2) ^ tx;
tx = (tx >>> 1) ^ tx;
return tx;
}

private static long hilbertPositionToXY(int z, int pos) {
pos = pos << (32 - 2 * z);

int i0 = deinterleave(pos);
int i1 = deinterleave(pos >>> 1);

int t0 = (i0 | i1) ^ 0xFFFF;
int t1 = i0 & i1;

int prefixT0 = prefixScan(t0);
int prefixT1 = prefixScan(t1);

int a = (((i0 ^ 0xFFFF) & prefixT1) | (i0 & prefixT0));

int resultX = (a ^ i1) >>> (16 - z);
int resultY = (a ^ i0 ^ i1) >>> (16 - z);
return ((long) resultX << 32) | resultY;
}

private static int hilbertXYToIndex(int z, int x, int y) {
x = x << (16 - z);
y = y << (16 - z);

int hA, hB, hC, hD;

int a1 = x ^ y;
int b1 = 0xFFFF ^ a1;
int c1 = 0xFFFF ^ (x | y);
int d1 = x & (y ^ 0xFFFF);

hA = a1 | (b1 >>> 1);
hB = (a1 >>> 1) ^ a1;

hC = ((c1 >>> 1) ^ (b1 & (d1 >>> 1))) ^ c1;
hD = ((a1 & (c1 >>> 1)) ^ (d1 >>> 1)) ^ d1;

int a2 = hA;
int b2 = hB;
int c2 = hC;
int d2 = hD;

hA = ((a2 & (a2 >>> 2)) ^ (b2 & (b2 >>> 2)));
hB = ((a2 & (b2 >>> 2)) ^ (b2 & ((a2 ^ b2) >>> 2)));

hC ^= ((a2 & (c2 >>> 2)) ^ (b2 & (d2 >>> 2)));
hD ^= ((b2 & (c2 >>> 2)) ^ ((a2 ^ b2) & (d2 >>> 2)));

int a3 = hA;
int b3 = hB;
int c3 = hC;
int d3 = hD;

hA = ((a3 & (a3 >>> 4)) ^ (b3 & (b3 >>> 4)));
hB = ((a3 & (b3 >>> 4)) ^ (b3 & ((a3 ^ b3) >>> 4)));

hC ^= ((a3 & (c3 >>> 4)) ^ (b3 & (d3 >>> 4)));
hD ^= ((b3 & (c3 >>> 4)) ^ ((a3 ^ b3) & (d3 >>> 4)));

int a4 = hA;
int b4 = hB;
int c4 = hC;
int d4 = hD;

hC ^= ((a4 & (c4 >>> 8)) ^ (b4 & (d4 >>> 8)));
hD ^= ((b4 & (c4 >>> 8)) ^ ((a4 ^ b4) & (d4 >>> 8)));

int a = hC ^ (hC >>> 1);
int b = hD ^ (hD >>> 1);

int i0 = x ^ y;
int i1 = b | (0xFFFF ^ (i0 | a));

return ((interleave(i1) << 1) | interleave(i0)) >>> (32 - 2 * z);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ private String getLastTileLogDetails() {
if (lastTile == null) {
blurb = "n/a";
} else {
blurb = "%d/%d/%d (z%d %s%%) %s".formatted(
blurb = "%d/%d/%d (z%d %s) %s".formatted(
lastTile.z(), lastTile.x(), lastTile.y(),
lastTile.z(), 100 * lastTile.progressOnLevel(),
lastTile.z(), Format.defaultInstance().percent(lastTile.progressOnLevel(config.bounds().tileExtents())),
lastTile.getDebugUrl()
);
}
Expand Down
Loading

0 comments on commit 3e1bf08

Please sign in to comment.