@Test public void whenPolygonInteriorRingFullyContainsTileExtentThenFeatureIsIgnored() { GeometryFactory gf = new GeometryFactory(); Coordinate[] ca = new Coordinate[5]; ca[0] = new Coordinate(-50, -50); ca[1] = new Coordinate(150, -50); ca[2] = new Coordinate(150, 150); ca[3] = new Coordinate(-50, 150); ca[4] = new Coordinate(-50, -50); LinearRing exterior = gf.createLinearRing(ca); ca[0] = new Coordinate(-10, -10); ca[1] = new Coordinate(-10, 110); ca[2] = new Coordinate(110, 110); ca[3] = new Coordinate(110, -10); ca[4] = new Coordinate(-10, -10); LinearRing interior = gf.createLinearRing(ca); Polygon p = gf.createPolygon(exterior, new LinearRing[] { interior }); double[] bbox = { 0, 0, 100, 100 }; SimpleFeatureTypeBuilder tBuilder = new SimpleFeatureTypeBuilder(); tBuilder.setName("test"); tBuilder.add("geom", Polygon.class); SimpleFeatureType featureType = tBuilder.buildFeatureType(); SimpleFeatureBuilder fBuilder = new SimpleFeatureBuilder(featureType); fBuilder.set("geom", p); SimpleFeature f = fBuilder.buildFeature(null); DefaultFeatureCollection fc = new DefaultFeatureCollection("test"); fc.add(f); List<Geometry> geom = SimpleFeaturesMVTEncoder.asMVTGeoms(fc, bbox, 4096, 256); assertEquals(0, geom.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);  }