You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@baremaps.apache.org by bc...@apache.org on 2023/10/08 14:42:32 UTC
[incubator-baremaps] 03/10: Serve contour tiles
This is an automated email from the ASF dual-hosted git repository.
bchapuis pushed a commit to branch gdal
in repository https://gitbox.apache.org/repos/asf/incubator-baremaps.git
commit 374c6858599a56dd946eba28cca059e0a777f434
Author: Bertil Chapuis <bc...@gmail.com>
AuthorDate: Sun Apr 23 12:44:02 2023 +0200
Serve contour tiles
---
.../java/org/apache/baremaps/cli/map/Contour.java | 82 +++++++++++++++
.../main/java/org/apache/baremaps/cli/map/Map.java | 2 +-
baremaps-core/pom.xml | 8 +-
.../apache/baremaps/raster/ContourTileStore.java | 73 +++++++------
.../main/java/org/apache/baremaps/raster/Main.java | 26 ++---
.../org/apache/baremaps/vectortile/Feature.java | 8 +-
.../baremaps/vectortile/VectorTileEncoder.java | 5 +-
.../baremaps/vectortile/VectorTileFunctions.java | 34 ++++--
.../vectortile/VectorTileFunctionsTest.java | 2 +-
.../apache/baremaps/vectortile/VectorTileTest.java | 4 +-
.../baremaps/vectortile/VectorTileViewer.java | 16 +--
.../apache/baremaps/server/ServerResources.java | 116 +++++++++++++++++++++
examples/contour/style.json | 4 +-
examples/contour/tileset.json | 11 +-
14 files changed, 304 insertions(+), 87 deletions(-)
diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Contour.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Contour.java
new file mode 100644
index 00000000..055456d5
--- /dev/null
+++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Contour.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed 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.cli.map;
+
+import static io.servicetalk.data.jackson.jersey.ServiceTalkJacksonSerializerFeature.contextResolverFor;
+import static org.apache.baremaps.server.DefaultObjectMapper.defaultObjectMapper;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.servicetalk.http.netty.HttpServers;
+import io.servicetalk.http.router.jersey.HttpJerseyRouterBuilder;
+import java.nio.file.Path;
+import java.util.concurrent.Callable;
+import org.apache.baremaps.database.tile.TileStore;
+import org.apache.baremaps.raster.ContourTileStore;
+import org.apache.baremaps.server.CorsFilter;
+import org.apache.baremaps.server.ServerResources;
+import org.glassfish.hk2.utilities.binding.AbstractBinder;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+
+@Command(name = "contour", description = "Start a tile server with caching capabilities.")
+public class Contour implements Callable<Integer> {
+
+ private static final Logger logger = LoggerFactory.getLogger(Contour.class);
+
+ @Option(names = {"--cache"}, paramLabel = "CACHE", description = "The caffeine cache directive.")
+ private String cache = "";
+
+ @Option(names = {"--tileset"}, paramLabel = "TILESET", description = "The tileset file.",
+ required = true)
+ private Path tileset;
+
+ @Option(names = {"--style"}, paramLabel = "STYLE", description = "The style file.",
+ required = true)
+ private Path style;
+
+ @Option(names = {"--host"}, paramLabel = "HOST", description = "The host of the server.")
+ private String host = "localhost";
+
+ @Option(names = {"--port"}, paramLabel = "PORT", description = "The port of the server.")
+ private int port = 9000;
+
+ @Override
+ public Integer call() throws Exception {
+ var objectMapper = defaultObjectMapper();
+ var tileStore = new ContourTileStore();
+
+ // Configure the application
+ var application =
+ new ResourceConfig().register(CorsFilter.class).register(ServerResources.class)
+ .register(contextResolverFor(objectMapper)).register(new AbstractBinder() {
+ @Override
+ protected void configure() {
+ bind(Contour.this.tileset).to(Path.class).named("tileset");
+ bind(style).to(Path.class).named("style");
+ bind(objectMapper).to(ObjectMapper.class);
+ bind(tileStore).to(TileStore.class);
+ }
+ });
+
+ var httpService = new HttpJerseyRouterBuilder().buildBlockingStreaming(application);
+ var serverContext = HttpServers.forPort(port).listenBlockingStreamingAndAwait(httpService);
+
+ logger.info("Listening on {}", serverContext.listenAddress());
+
+ serverContext.awaitShutdown();
+ return 0;
+ }
+}
diff --git a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java
index 0f0f1a4c..6744b00d 100644
--- a/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java
+++ b/baremaps-cli/src/main/java/org/apache/baremaps/cli/map/Map.java
@@ -24,7 +24,7 @@ import picocli.CommandLine.Command;
@Command(name = "map", description = "Map commands.",
subcommands = {Init.class, Export.class, Serve.class, Dev.class, StyleCommand.class,
- MBTiles.class},
+ MBTiles.class, Contour.class},
sortOptions = false)
public class Map implements Runnable {
diff --git a/baremaps-core/pom.xml b/baremaps-core/pom.xml
index 4b83e635..55159841 100644
--- a/baremaps-core/pom.xml
+++ b/baremaps-core/pom.xml
@@ -110,6 +110,10 @@ limitations under the License.
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial-extras</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.gdal</groupId>
+ <artifactId>gdal</artifactId>
+ </dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
@@ -118,10 +122,6 @@ limitations under the License.
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
</dependency>
- <dependency>
- <groupId>org.gdal</groupId>
- <artifactId>gdal</artifactId>
- </dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
diff --git a/baremaps-core/src/main/java/org/apache/baremaps/raster/ContourTileStore.java b/baremaps-core/src/main/java/org/apache/baremaps/raster/ContourTileStore.java
index 9e2b093b..bce42cd5 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/raster/ContourTileStore.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/raster/ContourTileStore.java
@@ -15,23 +15,24 @@ package org.apache.baremaps.raster;
import java.nio.ByteBuffer;
import java.nio.file.Paths;
import java.util.List;
+import java.util.Map;
import java.util.Vector;
-import java.util.stream.IntStream;
import java.util.stream.LongStream;
-
-import org.apache.baremaps.database.tile.Tile;
-import org.apache.baremaps.database.tile.TileStore;
-import org.apache.baremaps.database.tile.TileStoreException;
-import org.apache.baremaps.openstreetmap.utils.GeometryUtils;
-import org.apache.baremaps.openstreetmap.utils.ProjectionTransformer;
+import org.apache.baremaps.tilestore.TileCoord;
+import org.apache.baremaps.tilestore.TileStore;
+import org.apache.baremaps.tilestore.TileStoreException;
+import org.apache.baremaps.utils.GeometryUtils;
+import org.apache.baremaps.vectortile.Feature;
+import org.apache.baremaps.vectortile.Layer;
+import org.apache.baremaps.vectortile.VectorTileFunctions;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.WarpOptions;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
-import org.gdal.ogr.FieldDefn;
import org.gdal.ogr.ogr;
import org.gdal.osr.SpatialReference;
-import org.locationtech.jts.geom.util.GeometryTransformer;
+import org.locationtech.jts.geom.Envelope;
+import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.proj4j.ProjCoordinate;
public class ContourTileStore implements TileStore, AutoCloseable {
@@ -49,52 +50,62 @@ public class ContourTileStore implements TileStore, AutoCloseable {
}
@Override
- public ByteBuffer read(Tile tile) throws TileStoreException {
+ public ByteBuffer read(TileCoord tile) throws TileStoreException {
var sourceBand = sourceDataset.GetRasterBand(1);
var envelope = tile.envelope();
+ // Transform the extent to the source projection
+ var transformer = GeometryUtils.coordinateTransform(4326, 3857);
+ var min = transformer.transform(new ProjCoordinate(envelope.getMinX(), envelope.getMinY()),
+ new ProjCoordinate());
+ var max = transformer.transform(new ProjCoordinate(envelope.getMaxX(), envelope.getMaxY()),
+ new ProjCoordinate());
+ var targetEnvelope = new Envelope(min.x, max.x, min.y, max.y);
+
// Warp the raster to the requested extent
var rasterOptions = new WarpOptions(new Vector<>(List.of(
- "-of", "MEM",
- "-te", Double.toString(envelope.getMinX()), Double.toString(envelope.getMinY()), Double.toString(envelope.getMaxX()), Double.toString(envelope.getMaxY()),
- "-te_srs", "EPSG:4326")));
- var rasterDataset = gdal.Warp("", new Dataset[]{sourceDataset}, rasterOptions);
+ "-of", "MEM",
+ "-te", Double.toString(envelope.getMinX()), Double.toString(envelope.getMinY()),
+ Double.toString(envelope.getMaxX()), Double.toString(envelope.getMaxY()),
+ "-te_srs", "EPSG:4326")));
+ var rasterDataset = gdal.Warp("", new Dataset[] {sourceDataset}, rasterOptions);
var rasterBand = rasterDataset.GetRasterBand(1);
// Generate the contours
- //var wkt = rasterDataset.GetProjection();
- //var srs = new SpatialReference(wkt);
- var srs = new SpatialReference("EPSG:4326");
+ var wkt = rasterDataset.GetProjection();
+ var srs = new SpatialReference(wkt);
var vectorDriver = ogr.GetDriverByName("Memory");
var vectorDataSource = vectorDriver.CreateDataSource("vector");
var vectorLayer = vectorDataSource.CreateLayer("vector", srs, ogr.wkbLineString);
- gdal.ContourGenerateEx(rasterBand, vectorLayer, new Vector<>(List.of("LEVEL_INTERVAL=" + 10)));
+ gdal.ContourGenerateEx(rasterBand, vectorLayer, new Vector<>(List.of("LEVEL_INTERVAL=" + 50)));
// return the contours
- var geometries = LongStream.range(0, vectorLayer.GetFeatureCount())
- .mapToObj(vectorLayer::GetFeature)
- .map(feature -> feature.GetGeometryRef())
- .map(geometry -> GeometryUtils.deserialize(geometry.ExportToWkb()))
- .toList();
+ var features = LongStream.range(0, vectorLayer.GetFeatureCount())
+ .mapToObj(vectorLayer::GetFeature)
+ .map(feature -> feature.GetGeometryRef())
+ .map(geometry -> GeometryUtils.deserialize(geometry.ExportToWkb()))
+ .map(geometry -> VectorTileFunctions.asVectorTileGeom(geometry, targetEnvelope, 4096, 0, true))
+ .map(geometry -> new Feature(null, Map.of(), geometry))
+ .toList();
+
+ var vectorTile = VectorTileFunctions.asVectorTile(
+ new org.apache.baremaps.vectortile.Tile(List.of(new Layer("contours", 4096, features))));
- var transformer = GeometryUtils.coordinateTransform(4326, 3857);
- var min = transformer.transform(new ProjCoordinate(envelope.getMinX(), envelope.getMinY()), new ProjCoordinate());
- var max = transformer.transform(new ProjCoordinate(envelope.getMaxX(), envelope.getMaxY()), new ProjCoordinate());
rasterBand.delete();
rasterDataset.delete();
sourceBand.delete();
- return null;
+ return vectorTile;
}
@Override
- public void write(Tile tile, ByteBuffer blob) throws TileStoreException {
+ public void write(TileCoord tile, ByteBuffer blob) throws TileStoreException {
throw new UnsupportedOperationException();
}
@Override
- public void delete(Tile tile) throws TileStoreException {
+ public void delete(TileCoord tile) throws TileStoreException {
throw new UnsupportedOperationException();
}
@@ -105,8 +116,8 @@ public class ContourTileStore implements TileStore, AutoCloseable {
public static void main(String[] args) throws Exception {
var store = new ContourTileStore();
- store.read(new Tile(8492, 5792, 14).parent());
- }
+ store.read(new TileCoord(8492, 5792, 14).parent());
+ }
}
diff --git a/baremaps-core/src/main/java/org/apache/baremaps/raster/Main.java b/baremaps-core/src/main/java/org/apache/baremaps/raster/Main.java
index f447f5c5..e7dbd691 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/raster/Main.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/raster/Main.java
@@ -26,15 +26,15 @@ import org.gdal.osr.SpatialReference;
public class Main {
public static void main(String[] args) {
- var sourceFilename = Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857.tif")
- .toAbsolutePath().toString();
- var hillshadeFilename =
- Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857-hillshade.tif").toAbsolutePath()
- .toString();
- var outputFilename = Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857.shp")
- .toAbsolutePath().toString();
- var warpFilename = Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857-warp.tif")
- .toAbsolutePath().toString();
+ var sourceFilename = Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857.tif")
+ .toAbsolutePath().toString();
+ var hillshadeFilename =
+ Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857-hillshade.tif").toAbsolutePath()
+ .toString();
+ var outputFilename = Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857.shp")
+ .toAbsolutePath().toString();
+ var warpFilename = Paths.get("examples/contour/liecthenstein-aster-dem-v2-3857-warp.tif")
+ .toAbsolutePath().toString();
var dem = Paths.get("examples/contour/dem.xml")
.toAbsolutePath().toString();
@@ -44,10 +44,10 @@ public class Main {
planetContour();
- hillshade(sourceFilename, 1, hillshadeFilename, 45d, 315d);
- contourEx(hillshadeFilename, 1, outputFilename, 50, 0);
- warp(sourceFilename, warpFilename);
- shadow(hillshadeFilename, outputFilename);
+ hillshade(sourceFilename, 1, hillshadeFilename, 45d, 315d);
+ contourEx(hillshadeFilename, 1, outputFilename, 50, 0);
+ warp(sourceFilename, warpFilename);
+ shadow(hillshadeFilename, outputFilename);
}
public static void planetContour() {
diff --git a/baremaps-core/src/main/java/org/apache/baremaps/vectortile/Feature.java b/baremaps-core/src/main/java/org/apache/baremaps/vectortile/Feature.java
index 3fc3c587..7bd1d67a 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/vectortile/Feature.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/vectortile/Feature.java
@@ -26,7 +26,7 @@ import org.locationtech.jts.geom.Geometry;
*/
public class Feature {
- private long id;
+ private Long id;
private Map<String, Object> tags;
@@ -44,7 +44,7 @@ public class Feature {
* @param tags The tags of the feature.
* @param geometry The geometry of the feature.
*/
- public Feature(long id, Map<String, Object> tags, Geometry geometry) {
+ public Feature(Long id, Map<String, Object> tags, Geometry geometry) {
this.id = id;
this.tags = tags;
this.geometry = geometry;
@@ -55,7 +55,7 @@ public class Feature {
*
* @return The id of the feature.
*/
- public long getId() {
+ public Long getId() {
return id;
}
@@ -64,7 +64,7 @@ public class Feature {
*
* @param id The id of the feature.
*/
- public void setId(long id) {
+ public void setId(Long id) {
this.id = id;
}
diff --git a/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileEncoder.java b/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileEncoder.java
index a7c04910..0a679303 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileEncoder.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileEncoder.java
@@ -125,9 +125,10 @@ public class VectorTileEncoder {
cy = 0;
VectorTile.Tile.Feature.Builder builder = VectorTile.Tile.Feature.newBuilder();
- builder.setId(feature.getId());
+ if (feature.getId() != null) {
+ builder.setId(feature.getId());
+ }
builder.setType(encodeGeometryType(feature.getGeometry()));
-
encodeTag(feature.getTags(), builder::addTags);
encodeGeometry(feature.getGeometry(), builder::addGeometry);
diff --git a/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileFunctions.java b/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileFunctions.java
index 31888d83..59a45654 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileFunctions.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/vectortile/VectorTileFunctions.java
@@ -45,14 +45,13 @@ public class VectorTileFunctions {
* @param clipGeom A flag to clip the geometry
* @return The transformed geometry
*/
- public static Geometry asVectorTileGeom(Geometry geometry, Geometry envelope, int extent,
+ public static Geometry asVectorTileGeom(Geometry geometry, Envelope envelope, int extent,
int buffer, boolean clipGeom) {
// Scale the geometry to the extent of the tile
- var envelopeInternal = envelope.getEnvelopeInternal();
- double scaleX = extent / envelopeInternal.getWidth();
- double scaleY = extent / envelopeInternal.getHeight();
+ double scaleX = extent / envelope.getWidth();
+ double scaleY = extent / envelope.getHeight();
AffineTransformation affineTransformation = new AffineTransformation();
- affineTransformation.translate(-envelopeInternal.getMinX(), -envelopeInternal.getMinY());
+ affineTransformation.translate(-envelope.getMinX(), -envelope.getMinY());
affineTransformation.scale(scaleX, -scaleY);
affineTransformation.translate(0, extent);
Geometry scaledGeometry = affineTransformation.transform(geometry);
@@ -94,11 +93,16 @@ public class VectorTileFunctions {
* @return The transformed tile
*/
public static ByteBuffer asVectorTile(Tile vectorTile) {
- return new VectorTileEncoder()
- .encodeTile(vectorTile)
- .toByteString()
- .asReadOnlyByteBuffer();
-
+ ByteBuffer original = new VectorTileEncoder()
+ .encodeTile(vectorTile)
+ .toByteString()
+ .asReadOnlyByteBuffer();
+ ByteBuffer clone = ByteBuffer.allocate(original.capacity());
+ original.rewind();// copy from the beginning
+ clone.put(original);
+ original.rewind();
+ clone.flip();
+ return clone;
}
/**
@@ -108,10 +112,18 @@ public class VectorTileFunctions {
* @return The transformed layer
*/
public static ByteBuffer asVectorTileLayer(Layer layer) {
- return new VectorTileEncoder()
+ ByteBuffer original = new VectorTileEncoder()
.encodeLayer(layer)
.toByteString()
.asReadOnlyByteBuffer();
+
+ ByteBuffer clone = ByteBuffer.allocate(original.capacity());
+ original.rewind();// copy from the beginning
+ clone.put(original);
+ original.rewind();
+ clone.flip();
+
+ return clone;
}
/**
diff --git a/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileFunctionsTest.java b/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileFunctionsTest.java
index afeb8b89..181d493a 100644
--- a/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileFunctionsTest.java
+++ b/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileFunctionsTest.java
@@ -45,7 +45,7 @@ class VectorTileFunctionsTest {
// Transform the input geometry into a vector tile geometry
var outputGeom =
- VectorTileFunctions.asVectorTileGeom(inputGeom, envelope, extent, buffer, clipGeom);
+ VectorTileFunctions.asVectorTileGeom(inputGeom, envelope.getEnvelopeInternal(), extent, buffer, clipGeom);
// Check if the output geometry is not null
assertNotNull(outputGeom);
diff --git a/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileTest.java b/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileTest.java
index bc8fbfa9..2f2394a9 100644
--- a/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileTest.java
+++ b/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileTest.java
@@ -41,9 +41,9 @@ public class VectorTileTest {
public void endToEnd() {
var tile = new Tile(List.of(
new Layer("layer", 256, List.of(
- new Feature(1, Map.of("a", 1.0, "b", "2"),
+ new Feature(1l, Map.of("a", 1.0, "b", "2"),
GEOMETRY_FACTORY.createPoint(new Coordinate(1, 2))),
- new Feature(2, Map.of("c", 3.0, "d", "4"),
+ new Feature(2l, Map.of("c", 3.0, "d", "4"),
GEOMETRY_FACTORY.createPoint(new Coordinate(2, 3)))))));
var encoded = new VectorTileEncoder().encodeTile(tile);
diff --git a/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileViewer.java b/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileViewer.java
index faada968..a4f75369 100644
--- a/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileViewer.java
+++ b/baremaps-core/src/test/java/org/apache/baremaps/vectortile/VectorTileViewer.java
@@ -19,10 +19,8 @@ package org.apache.baremaps.vectortile;
import java.awt.*;
import java.awt.Dimension;
+import java.net.URL;
import java.nio.ByteBuffer;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.zip.GZIPInputStream;
import javax.swing.*;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.geom.Point;
@@ -34,10 +32,14 @@ import org.locationtech.jts.geom.Polygon;
public class VectorTileViewer {
public static void main(String... args) throws Exception {
- String arg =
- args.length > 0 ? args[0] : "baremaps-core/src/test/resources/vectortile/14-8493-5795.mvt";
- var path = Path.of(arg);
- try (var input = new GZIPInputStream(Files.newInputStream(path))) {
+ // String arg =
+ // args.length > 0 ? args[0] : "baremaps-core/src/test/resources/vectortile/14-8493-5795.mvt";
+ // var path = Path.of(arg);
+ // try (var input = new GZIPInputStream(Files.newInputStream(path))) {
+
+ var url = new URL("http://localhost:9000/tiles/14/8628/5750.mvt");
+
+ try (var input = url.openStream()) {
var buffer = ByteBuffer.wrap(input.readAllBytes());
var parsed = org.apache.baremaps.mvt.binary.VectorTile.Tile.parseFrom(buffer);
var tile = new VectorTileDecoder().decodeTile(parsed);
diff --git a/baremaps-server/src/main/java/org/apache/baremaps/server/ServerResources.java b/baremaps-server/src/main/java/org/apache/baremaps/server/ServerResources.java
new file mode 100644
index 00000000..781dbf68
--- /dev/null
+++ b/baremaps-server/src/main/java/org/apache/baremaps/server/ServerResources.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed 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.server;
+
+import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
+import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.nio.file.Path;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.ws.rs.GET;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.baremaps.config.ConfigReader;
+import org.apache.baremaps.tilestore.TileCoord;
+import org.apache.baremaps.tilestore.TileStore;
+import org.apache.baremaps.tilestore.TileStoreException;
+import org.apache.baremaps.vectortile.style.Style;
+import org.apache.baremaps.vectortile.tileset.Tileset;
+import org.apache.baremaps.vectortile.tileset.TilesetLayer;
+
+@Singleton
+@javax.ws.rs.Path("/")
+public class ServerResources {
+
+ private final Style style;
+
+ private final Tileset tileset;
+
+ private final TileStore tileStore;
+
+ public static final String TILE_ENCODING = "gzip";
+
+ public static final String TILE_TYPE = "application/vnd.mapbox-vector-tile";
+
+ @Inject
+ public ServerResources(@Named("tileset") Path tileset, @Named("style") Path style,
+ TileStore tileStore, ObjectMapper objectMapper) throws IOException {
+ this.tileStore = tileStore;
+ var configReader = new ConfigReader();
+ this.style = objectMapper.readValue(configReader.read(style), Style.class);
+ this.tileset = objectMapper.readValue(configReader.read(tileset), Tileset.class);
+
+ // Hide the SQL queries in production
+ for (TilesetLayer layer : this.tileset.getVectorLayers()) {
+ layer.setQueries(null);
+ }
+ }
+
+ @GET
+ @javax.ws.rs.Path("style.json")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Style getStyle() {
+ return style;
+ }
+
+ @GET
+ @javax.ws.rs.Path("tiles.json")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Tileset getTileset() {
+ return tileset;
+ }
+
+ @GET
+ @javax.ws.rs.Path("/tiles/{z}/{x}/{y}.mvt")
+ public Response getTile(@PathParam("z") int z, @PathParam("x") int x, @PathParam("y") int y) {
+ TileCoord tileCoord = new TileCoord(x, y, z);
+ try {
+ ByteBuffer blob = tileStore.read(tileCoord);
+ if (blob != null) {
+ var array = blob.array();
+ return Response.status(200) // lgtm [java/xss]
+ .header(ACCESS_CONTROL_ALLOW_ORIGIN, "*")
+ .header(CONTENT_TYPE, TILE_TYPE)
+ // .header(CONTENT_ENCODING, TILE_ENCODING)
+ .entity(array).build();
+ } else {
+ return Response.status(204).build();
+ }
+ } catch (TileStoreException ex) {
+ return Response.status(404).build();
+ }
+ }
+
+ @GET
+ @javax.ws.rs.Path("{path:.*}")
+ public Response get(@PathParam("path") String path) throws IOException {
+ if (path.equals("") || path.endsWith("/")) {
+ path += "server.html";
+ }
+ path = String.format("assets/%s", path);
+ try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path)) {
+ var bytes = inputStream.readAllBytes();
+ return Response.ok().entity(bytes).build();
+ } catch (NullPointerException | IOException e) {
+ return Response.status(404).build();
+ }
+ }
+}
diff --git a/examples/contour/style.json b/examples/contour/style.json
index 16047415..bb982ecc 100644
--- a/examples/contour/style.json
+++ b/examples/contour/style.json
@@ -14,10 +14,10 @@
"background-color" : "rgba(255, 255, 255, 1)"
}
}, {
- "id" : "aster_dem",
+ "id" : "contours",
"type" : "line",
"source" : "baremaps",
- "source-layer" : "aster_dem",
+ "source-layer" : "contours",
"layout" : {
"line-cap" : "round",
"line-join" : "round"
diff --git a/examples/contour/tileset.json b/examples/contour/tileset.json
index 74307e7b..2d729bdb 100644
--- a/examples/contour/tileset.json
+++ b/examples/contour/tileset.json
@@ -5,24 +5,17 @@
47.166,
14.0
],
- "bounds": [
- 9.471078,
- 47.04774,
- 9.636217,
- 47.27128
- ],
"tiles": [
"http://localhost:9000/tiles/{z}/{x}/{y}.mvt"
],
"database": "jdbc:postgresql://localhost:5432/baremaps?&user=baremaps&password=baremaps",
"vector_layers": [
{
- "id": "aster_dem",
+ "id": "contours",
"queries": [
{
"minzoom": 0,
- "maxzoom": 20,
- "sql": "SELECT ogc_fid, jsonb_build_object('elevation', elevation::text), wkb_geometry FROM aster_dem"
+ "maxzoom": 20
}
]
}