diff --git a/java/src/main/java/com/mlt/decoder/GeometryDecoder.java b/java/src/main/java/com/mlt/decoder/GeometryDecoder.java index 3132aea0..168c15cf 100644 --- a/java/src/main/java/com/mlt/decoder/GeometryDecoder.java +++ b/java/src/main/java/com/mlt/decoder/GeometryDecoder.java @@ -32,7 +32,6 @@ public static GeometryColumn decodeGeometryColumn( List numParts = null; List numRings = null; List vertexOffsets = null; - List mortonVertexBuffer = null; List vertexList = null; for (var i = 0; i < numStreams - 1; i++) { var geometryStreamMetadata = StreamMetadataDecoder.decode(tile, offset); @@ -109,6 +108,12 @@ public static Geometry[] decodeGeometry(GeometryColumn geometryColumn) { var vertexBuffer = geometryColumn.vertexList.stream().mapToInt(i -> i).toArray(); + var containsPolygon = + geometryColumn.geometryTypes.stream() + .anyMatch( + g -> + g == GeometryType.POLYGON.ordinal() + || g == GeometryType.MULTIPOLYGON.ordinal()); // TODO: refactor redundant code for (var geometryType : geometryTypes) { if (geometryType.equals(GeometryType.POINT.ordinal())) { @@ -146,17 +151,21 @@ public static Geometry[] decodeGeometry(GeometryColumn geometryColumn) { geometries[geometryCounter++] = geometryFactory.createMultiPoint(points); } } else if (geometryType.equals(GeometryType.LINESTRING.ordinal())) { + var numVertices = + containsPolygon + ? ringOffsets.get(ringOffsetsCounter++) + : partOffsets.get(partOffsetCounter++); + if (vertexOffsets == null || vertexOffsets.length == 0) { - var numVertices = partOffsets.get(partOffsetCounter++); var vertices = getLineString(vertexBuffer, vertexBufferOffset, numVertices, false); vertexBufferOffset += numVertices * 2; geometries[geometryCounter++] = geometryFactory.createLineString(vertices); } else { - var numVertices = partOffsets.get(partOffsetCounter++); var vertices = decodeDictionaryEncodedLineString( vertexBuffer, vertexOffsets, vertexOffsetsOffset, numVertices, false); vertexOffsetsOffset += numVertices; + geometries[geometryCounter++] = geometryFactory.createLineString(vertices); } } else if (geometryType.equals(GeometryType.POLYGON.ordinal())) { @@ -193,7 +202,11 @@ public static Geometry[] decodeGeometry(GeometryColumn geometryColumn) { var lineStrings = new LineString[numLineStrings]; if (vertexOffsets == null || vertexOffsets.length == 0) { for (var i = 0; i < numLineStrings; i++) { - var numVertices = partOffsets.get(partOffsetCounter++); + var numVertices = + containsPolygon + ? ringOffsets.get(ringOffsetsCounter++) + : partOffsets.get(partOffsetCounter++); + var vertices = getLineString(vertexBuffer, vertexBufferOffset, numVertices, false); lineStrings[i] = geometryFactory.createLineString(vertices); vertexBufferOffset += numVertices * 2; @@ -201,7 +214,11 @@ public static Geometry[] decodeGeometry(GeometryColumn geometryColumn) { geometries[geometryCounter++] = geometryFactory.createMultiLineString(lineStrings); } else { for (var i = 0; i < numLineStrings; i++) { - var numVertices = partOffsets.get(partOffsetCounter++); + var numVertices = + containsPolygon + ? ringOffsets.get(ringOffsetsCounter++) + : partOffsets.get(partOffsetCounter++); + var vertices = decodeDictionaryEncodedLineString( vertexBuffer, vertexOffsets, vertexOffsetsOffset, numVertices, false); @@ -275,8 +292,7 @@ public static Geometry[] decodeGeometryVectorized(GeometryVector geometryVector) var vertexBufferOffset = 0; var vertexOffsetsOffset = 0; - GeometryVector.MortonSettings mortonSettings = - geometryVector.mortonSettings.isPresent() ? geometryVector.mortonSettings.get() : null; + GeometryVector.MortonSettings mortonSettings = geometryVector.mortonSettings.orElse(null); var topologyVector = geometryVector.topologyVector; var geometryOffsets = topologyVector.geometryOffsets(); var partOffsets = topologyVector.partOffsets(); @@ -362,7 +378,7 @@ public static Geometry[] decodeGeometryVectorized(GeometryVector geometryVector) vertices = getLineString(vertexBuffer, vertexBufferOffset, numVertices, false); vertexBufferOffset += numVertices * 2; } else { - /** Currently only 2D coordinates are supported in this implementation */ + /* Currently only 2D coordinates are supported in this implementation */ vertices = geometryVector.vertexBufferType == GeometryVector.VertexBufferType.VEC_2 ? decodeDictionaryEncodedLineString( diff --git a/java/src/main/java/com/mlt/vector/geometry/GeometryVector.java b/java/src/main/java/com/mlt/vector/geometry/GeometryVector.java index 54318385..f7ee5ef5 100644 --- a/java/src/main/java/com/mlt/vector/geometry/GeometryVector.java +++ b/java/src/main/java/com/mlt/vector/geometry/GeometryVector.java @@ -134,6 +134,7 @@ public int getGeometryType(int index) { } public boolean containsPolygonGeometry() { + // TODO: get rid of this by only checking for the presence of partOffsets and ringOffsets? if (geometryTypes != null) { for (int i = 0; i < numGeometries; i++) { if (geometryTypes.get(i) == GeometryType.POLYGON.ordinal() @@ -162,7 +163,7 @@ public boolean hasNext() { @Override public Geometry next() { if (geometries == null) { - // TODO: implement lazy decoding + // TODO: implement lazy materialization geometries = GeometryDecoder.decodeGeometryVectorized(GeometryVector.this); } return geometries[index++]; diff --git a/java/src/test/java/com/mlt/decoder/MltDecoderTest.java b/java/src/test/java/com/mlt/decoder/MltDecoderTest.java index 4569be41..74b46c63 100644 --- a/java/src/test/java/com/mlt/decoder/MltDecoderTest.java +++ b/java/src/test/java/com/mlt/decoder/MltDecoderTest.java @@ -196,6 +196,18 @@ public void decodeMlTile_Z6() throws IOException { testTileSequential(tileId, TestSettings.OMT_MVT_PATH); } + @Test + public void decodeMlTile_Z10() throws IOException { + var tileId = String.format("%s_%s_%s", 10, 532, 684); + testTileSequential(tileId, TestSettings.OMT_MVT_PATH); + } + + @Test + public void decodeMlTile_Z13() throws IOException { + var tileId = String.format("%s_%s_%s", 13, 4265, 5467); + testTileSequential(tileId, TestSettings.OMT_MVT_PATH); + } + @Test @Disabled // java.lang.IllegalArgumentException: Invalid number of points in LineString (found 1 - must be 0