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 f5fa44f5bb66aa4c18611eb7b141367a67e82320
Author: Bertil Chapuis <[email protected]>
AuthorDate: Mon Sep 25 17:22:32 2023 +0200

    Fix envelope and levels
---
 .../apache/baremaps/raster/ContourTileStore.java   | 231 +++++++++++++--------
 .../org/apache/baremaps/tilestore/TileCoord.java   |   4 +-
 .../baremaps/database/calcite/CalciteTest.java     |   1 -
 .../apache/baremaps/server/TilesetResource.java    |   5 +-
 examples/contour/dem.xml                           |   2 +-
 5 files changed, 149 insertions(+), 94 deletions(-)

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 5eeb5855..2aead3c5 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
@@ -12,12 +12,6 @@
 
 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.LongStream;
 import org.apache.baremaps.tilestore.TileCoord;
 import org.apache.baremaps.tilestore.TileStore;
 import org.apache.baremaps.tilestore.TileStoreException;
@@ -32,91 +26,152 @@ import org.gdal.gdal.gdal;
 import org.gdal.gdalconst.gdalconstConstants;
 import org.gdal.ogr.ogr;
 import org.gdal.osr.SpatialReference;
-import org.locationtech.jts.geom.Envelope;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.GeometryFactory;
 import org.locationtech.proj4j.ProjCoordinate;
 
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.LongStream;
+
 public class ContourTileStore implements TileStore, AutoCloseable {
 
-  static {
-    gdal.AllRegister();
-    ogr.RegisterAll();
-  }
-
-  private final Dataset sourceDataset;
-
-  public ContourTileStore() {
-    var dem = Paths.get("dem.xml").toAbsolutePath().toString();
-    sourceDataset = gdal.Open(dem, gdalconstConstants.GA_ReadOnly);
-  }
-
-  @Override
-  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);
-    var rasterBand = rasterDataset.GetRasterBand(1);
-
-    // Generate the contours
-    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=" + 50)));
-
-    // return the contours
-    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 VectorTile(List.of(new Layer("contours", 4096, 
features))));
-
-    rasterBand.delete();
-    rasterDataset.delete();
-    sourceBand.delete();
-
-    return vectorTile;
-  }
-
-  @Override
-  public void write(TileCoord tile, ByteBuffer blob) throws TileStoreException 
{
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void delete(TileCoord tile) throws TileStoreException {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void close() throws Exception {
-    sourceDataset.delete();
-  }
-
-  public static void main(String[] args) throws Exception {
-    var store = new ContourTileStore();
-    store.read(new TileCoord(8492, 5792, 14).parent());
-  }
+    static {
+        gdal.AllRegister();
+        ogr.RegisterAll();
+    }
+
+    private final Map<Integer, Dataset> datasets = new HashMap<>();
+
+    public ContourTileStore() {
+    }
+
+    public Dataset initDataset(Integer zoom) {
+        try {
+            var dem = Files.readString(Paths.get("dem.xml"));
+            dem = dem.replace("<TileLevel>0</TileLevel>", "<TileLevel>" + zoom 
+ "</TileLevel>");
+            return gdal.Open(dem, gdalconstConstants.GA_ReadOnly);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+
+    @Override
+    public synchronized ByteBuffer read(TileCoord tile) throws 
TileStoreException {
+        var dataset = datasets.computeIfAbsent(tile.z(), this::initDataset);
+        var sourceBand = dataset.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 buffer = (max.x - min.x) / 4096 * 16;
+
+        var targetEnvelope = new GeometryFactory().createPolygon(new 
Coordinate[]{
+                new Coordinate(min.x, min.y),
+                new Coordinate(min.x, max.y),
+                new Coordinate(max.x, max.y),
+                new Coordinate(max.x, min.y),
+                new Coordinate(min.x, min.y)
+        });
+        var bufferedEnvelope = targetEnvelope.buffer(buffer);
+
+        // Warp the raster to the requested extent
+        var rasterOptions = new WarpOptions(new Vector<>(List.of(
+                "-of", "MEM",
+                "-te", 
Double.toString(bufferedEnvelope.getEnvelopeInternal().getMinX()), 
Double.toString(bufferedEnvelope.getEnvelopeInternal().getMinY()),
+                
Double.toString(bufferedEnvelope.getEnvelopeInternal().getMaxX()), 
Double.toString(bufferedEnvelope.getEnvelopeInternal().getMaxY()),
+                "-te_srs", "EPSG:3857")));
+        var rasterDataset = gdal.Warp("", new Dataset[]{dataset}, 
rasterOptions);
+        var rasterBand = rasterDataset.GetRasterBand(1);
+
+        // Generate the contours
+        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);
+
+
+        String levels = IntStream.range(1, 1000)
+                .mapToObj(i -> i * 10)
+                .filter(l -> {
+                    if (tile.z() <= 9) {
+                        return l % 1000 == 0;
+                    } else if (tile.z() <= 10) {
+                        return l % 800 == 0;
+                    } else if (tile.z() <= 11) {
+                        return l % 400 == 0;
+                    } else if (tile.z() <= 12) {
+                        return l % 200 == 0;
+                    } else if (tile.z() <= 13) {
+                        return l % 100 == 0;
+                    } else if (tile.z() <= 14) {
+                        return l % 50 == 0;
+                    } else {
+                        return l % 10 == 0;
+                    }
+                })
+                .map(Object::toString)
+                .collect(Collectors.joining(","));
+
+        gdal.ContourGenerateEx(rasterBand, vectorLayer, new 
Vector<>(List.of("FIXED_LEVELS=" + levels)));
+
+        // return the contours
+        var geometries = LongStream.range(0, vectorLayer.GetFeatureCount())
+                .mapToObj(vectorLayer::GetFeature)
+                .map(feature -> feature.GetGeometryRef())
+                .map(geometry -> 
GeometryUtils.deserialize(geometry.ExportToWkb()))
+                .map(targetEnvelope::intersection)
+                .toList();
+
+        var features = geometries.stream()
+                .map(geometry -> 
VectorTileFunctions.asVectorTileGeom(geometry, 
targetEnvelope.getEnvelopeInternal(), 4096, 0,
+                        true))
+                .filter(geometry -> geometry.getCoordinates().length >= 2)
+                .map(geometry -> new Feature(null, Map.of(), geometry))
+                .toList();
+
+        var vectorTile = VectorTileFunctions
+                .asVectorTile(new VectorTile(List.of(new Layer("contours", 
4096, features))));
+
+        rasterBand.delete();
+        rasterDataset.delete();
+        sourceBand.delete();
+
+        return vectorTile;
+    }
+
+    @Override
+    public void write(TileCoord tile, ByteBuffer blob) throws 
TileStoreException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void delete(TileCoord tile) throws TileStoreException {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void close() throws Exception {
+        datasets.values().forEach(Dataset::delete);
+    }
+
+    public static void main(String[] args) throws Exception {
+        var store = new ContourTileStore();
+        store.read(new TileCoord(8492, 5792, 14).parent());
+    }
 
 }
diff --git 
a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileCoord.java 
b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileCoord.java
index 1953e634..c08505e7 100644
--- a/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileCoord.java
+++ b/baremaps-core/src/main/java/org/apache/baremaps/tilestore/TileCoord.java
@@ -203,8 +203,8 @@ public final class TileCoord implements 
Comparable<TileCoord> {
     return new Envelope(x1, x2, y1, y2);
   }
 
-  public static double tile2lon(int x, int z) {
-    return x / Math.pow(2.0, z) * 360.0 - 180;
+  public static double tile2lon(double x, double z) {
+    return x / Math.pow(2.0, z) * 360.0 - 180.0;
   }
 
   public static double tile2lat(int y, int z) {
diff --git 
a/baremaps-core/src/test/java/org/apache/baremaps/database/calcite/CalciteTest.java
 
b/baremaps-core/src/test/java/org/apache/baremaps/database/calcite/CalciteTest.java
index ed22aee5..ea32f16b 100644
--- 
a/baremaps-core/src/test/java/org/apache/baremaps/database/calcite/CalciteTest.java
+++ 
b/baremaps-core/src/test/java/org/apache/baremaps/database/calcite/CalciteTest.java
@@ -44,7 +44,6 @@ import org.locationtech.jts.geom.*;
 
 public class CalciteTest {
 
-
   @Test
   public void test() throws SQLException {
     GeometryFactory geometryFactory = new GeometryFactory();
diff --git 
a/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java 
b/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java
index d2434b84..2ebcb816 100644
--- 
a/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java
+++ 
b/baremaps-server/src/main/java/org/apache/baremaps/server/TilesetResource.java
@@ -17,13 +17,14 @@
 
 package org.apache.baremaps.server;
 
-import java.util.function.Supplier;
+import org.apache.baremaps.vectortile.tileset.Tileset;
+
 import javax.inject.Inject;
 import javax.inject.Singleton;
 import javax.ws.rs.GET;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
-import org.apache.baremaps.vectortile.tileset.Tileset;
+import java.util.function.Supplier;
 
 /**
  * A resource that provides access to the tileset file. Only suitable for 
development purposes, as
diff --git a/examples/contour/dem.xml b/examples/contour/dem.xml
index 178ca466..ac8b8e1d 100644
--- a/examples/contour/dem.xml
+++ b/examples/contour/dem.xml
@@ -11,7 +11,7 @@
         <UpperLeftY>20037508.34</UpperLeftY>
         <LowerRightX>20037508.34</LowerRightX>
         <LowerRightY>-20037508.34</LowerRightY>
-        <TileLevel>14</TileLevel>
+        <TileLevel>0</TileLevel>
         <TileCountX>1</TileCountX>
         <TileCountY>1</TileCountY>
         <YOrigin>top</YOrigin>

Reply via email to