@Test public void testNahkela() throws Exception { WFSTileGrid grid = new WFSTileGrid(new double[] { -548576, 6291456, -548576 + (8192*256), 6291456 + (8192*256) }, 15); Map<String, Object> json; try (InputStream in = getClass().getClassLoader().getResourceAsStream("nahkela.json")) { ObjectMapper om = new ObjectMapper(); json = om.readValue(in, new TypeReference<HashMap<String, Object>>() {}); } CoordinateReferenceSystem crs = CRS.decode("EPSG:3067"); SimpleFeatureType schema = GeoJSONSchemaDetector.getSchema(json, crs); SimpleFeatureCollection sfc = GeoJSONReader2.toFeatureCollection(json, schema); double[] bbox = grid.getTileExtent(new TileCoord(10, 456, 826)); List<Geometry> mvtGeoms = SimpleFeaturesMVTEncoder.asMVTGeoms(sfc, bbox, 4096, 256); assertEquals(1, mvtGeoms.size()); }
public static List<Geometry> asMVTGeoms(SimpleFeatureCollection sfc, double[] bbox, int extent, int buffer) { if (sfc.isEmpty()) { return Collections.emptyList(); } Envelope tileEnvelope = new Envelope(bbox[0], bbox[2], bbox[1], bbox[3]); Envelope clipEnvelope = new Envelope(tileEnvelope); if (buffer > 0) { double bufferSizePercent = (double) buffer / extent; double deltaX = bufferSizePercent * tileEnvelope.getWidth(); double deltaY = bufferSizePercent * tileEnvelope.getHeight(); clipEnvelope.expandBy(deltaX, deltaY); } RectangleIntersects tileIntersects = new RectangleIntersects((Polygon) GF.toGeometry(tileEnvelope)); Envelope mvtBufferedEnvelope = new Envelope(-buffer, extent + buffer, -buffer, extent + buffer); Geometry mvtClipGeom = GF.toGeometry(mvtBufferedEnvelope); double translateX = tileEnvelope.getMinX(); double translateY = tileEnvelope.getMaxY(); double scaleX = (double) extent / tileEnvelope.getWidth(); double scaleY = -((double) extent / tileEnvelope.getHeight()); ToMVTSpace snapToGrid = new ToMVTSpace(translateX, translateY, scaleX, scaleY); GeometryEditor editor = new GeometryEditor(GF); List<Geometry> mvtGeoms = new ArrayList<>(); try (SimpleFeatureIterator it = sfc.features()) { while (it.hasNext()) { SimpleFeature sf = it.next(); Geometry geom = (Geometry) sf.getDefaultGeometry(); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (geom instanceof Point) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } } else if (geom instanceof MultiPoint) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = removePointsOutsideOfEnvelope((MultiPoint) geom, clipEnvelope); } else { if (!tileEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = notDisjoint(tileIntersects, geom); if (geom == null || geom.isEmpty()) { continue; } } geom = editor.edit(geom, snapToGrid); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (!(geom instanceof Point || geom instanceof MultiPoint)) { geom = VWSimplifier.simplify(geom, 0.5); try { geom = mvtClipGeom.intersection(geom); if (geom == null || geom.isEmpty()) { continue; } } catch (TopologyException ignore) { continue; } } geom.setUserData(sf); mvtGeoms.add(geom); } } return mvtGeoms; }
SimpleFeaturesMVTEncoder { public static List<Geometry> asMVTGeoms(SimpleFeatureCollection sfc, double[] bbox, int extent, int buffer) { if (sfc.isEmpty()) { return Collections.emptyList(); } Envelope tileEnvelope = new Envelope(bbox[0], bbox[2], bbox[1], bbox[3]); Envelope clipEnvelope = new Envelope(tileEnvelope); if (buffer > 0) { double bufferSizePercent = (double) buffer / extent; double deltaX = bufferSizePercent * tileEnvelope.getWidth(); double deltaY = bufferSizePercent * tileEnvelope.getHeight(); clipEnvelope.expandBy(deltaX, deltaY); } RectangleIntersects tileIntersects = new RectangleIntersects((Polygon) GF.toGeometry(tileEnvelope)); Envelope mvtBufferedEnvelope = new Envelope(-buffer, extent + buffer, -buffer, extent + buffer); Geometry mvtClipGeom = GF.toGeometry(mvtBufferedEnvelope); double translateX = tileEnvelope.getMinX(); double translateY = tileEnvelope.getMaxY(); double scaleX = (double) extent / tileEnvelope.getWidth(); double scaleY = -((double) extent / tileEnvelope.getHeight()); ToMVTSpace snapToGrid = new ToMVTSpace(translateX, translateY, scaleX, scaleY); GeometryEditor editor = new GeometryEditor(GF); List<Geometry> mvtGeoms = new ArrayList<>(); try (SimpleFeatureIterator it = sfc.features()) { while (it.hasNext()) { SimpleFeature sf = it.next(); Geometry geom = (Geometry) sf.getDefaultGeometry(); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (geom instanceof Point) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } } else if (geom instanceof MultiPoint) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = removePointsOutsideOfEnvelope((MultiPoint) geom, clipEnvelope); } else { if (!tileEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = notDisjoint(tileIntersects, geom); if (geom == null || geom.isEmpty()) { continue; } } geom = editor.edit(geom, snapToGrid); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (!(geom instanceof Point || geom instanceof MultiPoint)) { geom = VWSimplifier.simplify(geom, 0.5); try { geom = mvtClipGeom.intersection(geom); if (geom == null || geom.isEmpty()) { continue; } } catch (TopologyException ignore) { continue; } } geom.setUserData(sf); mvtGeoms.add(geom); } } return mvtGeoms; } }
SimpleFeaturesMVTEncoder { public static List<Geometry> asMVTGeoms(SimpleFeatureCollection sfc, double[] bbox, int extent, int buffer) { if (sfc.isEmpty()) { return Collections.emptyList(); } Envelope tileEnvelope = new Envelope(bbox[0], bbox[2], bbox[1], bbox[3]); Envelope clipEnvelope = new Envelope(tileEnvelope); if (buffer > 0) { double bufferSizePercent = (double) buffer / extent; double deltaX = bufferSizePercent * tileEnvelope.getWidth(); double deltaY = bufferSizePercent * tileEnvelope.getHeight(); clipEnvelope.expandBy(deltaX, deltaY); } RectangleIntersects tileIntersects = new RectangleIntersects((Polygon) GF.toGeometry(tileEnvelope)); Envelope mvtBufferedEnvelope = new Envelope(-buffer, extent + buffer, -buffer, extent + buffer); Geometry mvtClipGeom = GF.toGeometry(mvtBufferedEnvelope); double translateX = tileEnvelope.getMinX(); double translateY = tileEnvelope.getMaxY(); double scaleX = (double) extent / tileEnvelope.getWidth(); double scaleY = -((double) extent / tileEnvelope.getHeight()); ToMVTSpace snapToGrid = new ToMVTSpace(translateX, translateY, scaleX, scaleY); GeometryEditor editor = new GeometryEditor(GF); List<Geometry> mvtGeoms = new ArrayList<>(); try (SimpleFeatureIterator it = sfc.features()) { while (it.hasNext()) { SimpleFeature sf = it.next(); Geometry geom = (Geometry) sf.getDefaultGeometry(); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (geom instanceof Point) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } } else if (geom instanceof MultiPoint) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = removePointsOutsideOfEnvelope((MultiPoint) geom, clipEnvelope); } else { if (!tileEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = notDisjoint(tileIntersects, geom); if (geom == null || geom.isEmpty()) { continue; } } geom = editor.edit(geom, snapToGrid); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (!(geom instanceof Point || geom instanceof MultiPoint)) { geom = VWSimplifier.simplify(geom, 0.5); try { geom = mvtClipGeom.intersection(geom); if (geom == null || geom.isEmpty()) { continue; } } catch (TopologyException ignore) { continue; } } geom.setUserData(sf); mvtGeoms.add(geom); } } return mvtGeoms; }  }
SimpleFeaturesMVTEncoder { public static List<Geometry> asMVTGeoms(SimpleFeatureCollection sfc, double[] bbox, int extent, int buffer) { if (sfc.isEmpty()) { return Collections.emptyList(); } Envelope tileEnvelope = new Envelope(bbox[0], bbox[2], bbox[1], bbox[3]); Envelope clipEnvelope = new Envelope(tileEnvelope); if (buffer > 0) { double bufferSizePercent = (double) buffer / extent; double deltaX = bufferSizePercent * tileEnvelope.getWidth(); double deltaY = bufferSizePercent * tileEnvelope.getHeight(); clipEnvelope.expandBy(deltaX, deltaY); } RectangleIntersects tileIntersects = new RectangleIntersects((Polygon) GF.toGeometry(tileEnvelope)); Envelope mvtBufferedEnvelope = new Envelope(-buffer, extent + buffer, -buffer, extent + buffer); Geometry mvtClipGeom = GF.toGeometry(mvtBufferedEnvelope); double translateX = tileEnvelope.getMinX(); double translateY = tileEnvelope.getMaxY(); double scaleX = (double) extent / tileEnvelope.getWidth(); double scaleY = -((double) extent / tileEnvelope.getHeight()); ToMVTSpace snapToGrid = new ToMVTSpace(translateX, translateY, scaleX, scaleY); GeometryEditor editor = new GeometryEditor(GF); List<Geometry> mvtGeoms = new ArrayList<>(); try (SimpleFeatureIterator it = sfc.features()) { while (it.hasNext()) { SimpleFeature sf = it.next(); Geometry geom = (Geometry) sf.getDefaultGeometry(); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (geom instanceof Point) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } } else if (geom instanceof MultiPoint) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = removePointsOutsideOfEnvelope((MultiPoint) geom, clipEnvelope); } else { if (!tileEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = notDisjoint(tileIntersects, geom); if (geom == null || geom.isEmpty()) { continue; } } geom = editor.edit(geom, snapToGrid); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (!(geom instanceof Point || geom instanceof MultiPoint)) { geom = VWSimplifier.simplify(geom, 0.5); try { geom = mvtClipGeom.intersection(geom); if (geom == null || geom.isEmpty()) { continue; } } catch (TopologyException ignore) { continue; } } geom.setUserData(sf); mvtGeoms.add(geom); } } return mvtGeoms; }  static byte[] encodeToByteArray(SimpleFeatureCollection sfc,
            String layer, double[] bbox, int extent, int buffer); static VectorTile.Tile encode(SimpleFeatureCollection sfc,
            String layer, double[] bbox, int extent, int buffer); static List<Geometry> asMVTGeoms(SimpleFeatureCollection sfc, double[] bbox, int extent, int buffer); }
SimpleFeaturesMVTEncoder { public static List<Geometry> asMVTGeoms(SimpleFeatureCollection sfc, double[] bbox, int extent, int buffer) { if (sfc.isEmpty()) { return Collections.emptyList(); } Envelope tileEnvelope = new Envelope(bbox[0], bbox[2], bbox[1], bbox[3]); Envelope clipEnvelope = new Envelope(tileEnvelope); if (buffer > 0) { double bufferSizePercent = (double) buffer / extent; double deltaX = bufferSizePercent * tileEnvelope.getWidth(); double deltaY = bufferSizePercent * tileEnvelope.getHeight(); clipEnvelope.expandBy(deltaX, deltaY); } RectangleIntersects tileIntersects = new RectangleIntersects((Polygon) GF.toGeometry(tileEnvelope)); Envelope mvtBufferedEnvelope = new Envelope(-buffer, extent + buffer, -buffer, extent + buffer); Geometry mvtClipGeom = GF.toGeometry(mvtBufferedEnvelope); double translateX = tileEnvelope.getMinX(); double translateY = tileEnvelope.getMaxY(); double scaleX = (double) extent / tileEnvelope.getWidth(); double scaleY = -((double) extent / tileEnvelope.getHeight()); ToMVTSpace snapToGrid = new ToMVTSpace(translateX, translateY, scaleX, scaleY); GeometryEditor editor = new GeometryEditor(GF); List<Geometry> mvtGeoms = new ArrayList<>(); try (SimpleFeatureIterator it = sfc.features()) { while (it.hasNext()) { SimpleFeature sf = it.next(); Geometry geom = (Geometry) sf.getDefaultGeometry(); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (geom instanceof Point) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } } else if (geom instanceof MultiPoint) { if (!clipEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = removePointsOutsideOfEnvelope((MultiPoint) geom, clipEnvelope); } else { if (!tileEnvelope.intersects(geom.getEnvelopeInternal())) { continue; } geom = notDisjoint(tileIntersects, geom); if (geom == null || geom.isEmpty()) { continue; } } geom = editor.edit(geom, snapToGrid); if (geom == null || geom.isEmpty()) { continue; } geom = multiGeometriesWithOneGeometryToSingle(geom); if (!(geom instanceof Point || geom instanceof MultiPoint)) { geom = VWSimplifier.simplify(geom, 0.5); try { geom = mvtClipGeom.intersection(geom); if (geom == null || geom.isEmpty()) { continue; } } catch (TopologyException ignore) { continue; } } geom.setUserData(sf); mvtGeoms.add(geom); } } return mvtGeoms; }  static byte[] encodeToByteArray(SimpleFeatureCollection sfc,
            String layer, double[] bbox, int extent, int buffer); static VectorTile.Tile encode(SimpleFeatureCollection sfc,
            String layer, double[] bbox, int extent, int buffer); static List<Geometry> asMVTGeoms(SimpleFeatureCollection sfc, double[] bbox, int extent, int buffer);  }