Skip to content

Commit

Permalink
Add support for PMTiles (#794)
Browse files Browse the repository at this point in the history
Enable the export of vector tiles in the PMTiles format. Most of the necessary functions have been ported from [go-pmtiles](https://github.com/protomaps/go-pmtiles) to Java.
  • Loading branch information
bchapuis authored Nov 26, 2023
1 parent 70f6d5f commit 1764a6a
Show file tree
Hide file tree
Showing 33 changed files with 1,896 additions and 85 deletions.
7 changes: 6 additions & 1 deletion .run/basemap-dev.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
<configuration default="false" name="basemap-dev" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.apache.baremaps.cli.Baremaps" />
<module name="baremaps-cli" />
<option name="PROGRAM_PARAMETERS" value="map dev --tileset tileset.js --style style.js" />
<option name="PROGRAM_PARAMETERS" value="map dev --tileset tileset.js --style style.js --log-level DEBUG" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/basemap" />
<extension name="software.aws.toolkits.jetbrains.core.execution.JavaAwsConnectionExtension">
<option name="credential" />
<option name="region" />
<option name="useCurrentConnection" value="false" />
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
Expand Down
11 changes: 11 additions & 0 deletions .run/basemap-export-mbtiles.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="basemap-export-mbtiles" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.apache.baremaps.cli.Baremaps" />
<module name="baremaps-cli" />
<option name="PROGRAM_PARAMETERS" value="map export --tileset tileset.js --repository tiles.mbtiles --format mbtiles" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/basemap" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
11 changes: 11 additions & 0 deletions .run/basemap-export-pmtiles.run.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="basemap-export-pmtiles" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.apache.baremaps.cli.Baremaps" />
<module name="baremaps-cli" />
<option name="PROGRAM_PARAMETERS" value="map export --tileset tileset.js --repository tiles.mbtiles --format pmtiles" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/basemap" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>
2 changes: 1 addition & 1 deletion .run/basemap-workflow.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<configuration default="false" name="basemap-workflow" type="Application" factoryName="Application">
<option name="MAIN_CLASS_NAME" value="org.apache.baremaps.cli.Baremaps" />
<module name="baremaps-cli" />
<option name="PROGRAM_PARAMETERS" value="workflow execute --file workflow.js" />
<option name="PROGRAM_PARAMETERS" value="workflow execute --file import.js" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/basemap" />
<method v="2">
<option name="Make" enabled="true" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,10 @@ public void delete(TileCoord tileCoord) throws TileStoreException {
tileStore.delete(tileCoord);
cache.invalidate(tileCoord);
}

@Override
public void close() throws Exception {
tileStore.close();
cache.cleanUp();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import java.util.List;

/** Represents a store for tiles. */
public interface TileStore {
public interface TileStore extends AutoCloseable {

/**
* Reads the content of a tile.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,14 @@ public TileStoreException(String message) {
public TileStoreException(Throwable cause) {
super(cause);
}

/**
* Constructs a {@code BlobStoreException} with the specified detail message and cause.
*
* @param message the message
* @param cause the cause
*/
public TileStoreException(String message, Throwable cause) {
super(message, cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,9 @@ public void delete(TileCoord tileCoord) throws TileStoreException {
public Path resolve(TileCoord tileCoord) {
return path.resolve(String.format("%s/%s/%s.mvt", tileCoord.z(), tileCoord.x(), tileCoord.y()));
}

@Override
public void close() {
// Do nothing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,9 @@ public void writeMetadata(Map<String, String> metadata) throws IOException {
private static int reverseY(int y, int z) {
return (int) (Math.pow(2.0, z) - 1 - y);
}

@Override
public void close() throws Exception {
// Do nothing
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.baremaps.tilestore.pmtiles;

import java.io.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

enum Compression {
Unknown,
None,
Gzip,
Brotli,
Zstd;

InputStream decompress(InputStream inputStream) throws IOException {
return switch (this) {
case None -> inputStream;
case Gzip -> decompressGzip(inputStream);
case Brotli -> decompressBrotli(inputStream);
case Zstd -> decompressZstd(inputStream);
default -> throw new RuntimeException("Unknown compression");
};
}

static InputStream decompressGzip(InputStream inputStream) throws IOException {
return new GZIPInputStream(inputStream);
}

static InputStream decompressBrotli(InputStream buffer) {
throw new RuntimeException("Brotli compression not implemented");
}

static InputStream decompressZstd(InputStream buffer) {
throw new RuntimeException("Zstd compression not implemented");
}

OutputStream compress(OutputStream outputStream) throws IOException {
return switch (this) {
case None -> outputStream;
case Gzip -> compressGzip(outputStream);
case Brotli -> compressBrotli(outputStream);
case Zstd -> compressZstd(outputStream);
default -> throw new RuntimeException("Unknown compression");
};
}

static OutputStream compressGzip(OutputStream outputStream) throws IOException {
return new GZIPOutputStream(outputStream);
}

static OutputStream compressBrotli(OutputStream outputStream) {
throw new RuntimeException("Brotli compression not implemented");
}

static OutputStream compressZstd(OutputStream outputStream) {
throw new RuntimeException("Zstd compression not implemented");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.baremaps.tilestore.pmtiles;

class Directories {

private final byte[] root;
private final byte[] leaves;
private final int numLeaves;

public Directories(byte[] root, byte[] leaves, int numLeaves) {
this.root = root;
this.leaves = leaves;
this.numLeaves = numLeaves;
}

public byte[] getRoot() {
return root;
}

public byte[] getLeaves() {
return leaves;
}

public int getNumLeaves() {
return numLeaves;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.baremaps.tilestore.pmtiles;

class Entry {
private long tileId;
private long offset;
private long length;
private long runLength;

public Entry() {}

public Entry(long tileId, long offset, long length, long runLength) {
this.tileId = tileId;
this.offset = offset;
this.length = length;
this.runLength = runLength;
}

public long getTileId() {
return tileId;
}

public void setTileId(long tileId) {
this.tileId = tileId;
}

public long getOffset() {
return offset;
}

public void setOffset(long offset) {
this.offset = offset;
}

public long getLength() {
return length;
}

public void setLength(long length) {
this.length = length;
}

public long getRunLength() {
return runLength;
}

public void setRunLength(long runLength) {
this.runLength = runLength;
}
}
Loading

0 comments on commit 1764a6a

Please sign in to comment.