package com.wdtinc.mapbox_vector_tile.adapt.jts; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; import org.locationtech.jts.geom.LineString; import org.locationtech.jts.geom.MultiPolygon; import org.locationtech.jts.geom.Polygon; import org.locationtech.jts.geom.PrecisionModel; import org.locationtech.jts.geom.impl.PackedCoordinateSequenceFactory; import com.wdtinc.mapbox_vector_tile.adapt.jts.model.JtsLayer; import com.wdtinc.mapbox_vector_tile.adapt.jts.model.JtsMvt; import com.wdtinc.mapbox_vector_tile.util.JtsGeomStats; import org.junit.Test; import org.slf4j.LoggerFactory; import java.io.File; import java.io.IOException; import java.util.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * Test reading MVTs. */ public final class MvtReaderTest { private static final double DOUBLE_DELTA = 1e-10; private static final int NUMBER_OF_DIMENSIONS = 2; private static final int SRID = 0; @Test public void testLayers() { try { JtsMvt result = MvtReader.loadMvt( new File("src/test/resources/vec_tile_test/game.mvt"), createGeometryFactory(), new TagKeyValueMapConverter()); final Collection<JtsLayer> layerValues = result.getLayers(); final int actualCount = layerValues.size(); final int expectedCount = 4; assertEquals(expectedCount, actualCount); assertTrue(result.getLayer("health") != null); assertTrue(result.getLayer("bombs") != null); assertTrue(result.getLayer("enemies") != null); assertTrue(result.getLayer("bullet") != null); // verify order final Iterator<JtsLayer> layerIterator = layerValues.iterator(); assertTrue(layerIterator.next() == result.getLayer("bombs")); assertTrue(layerIterator.next() == result.getLayer("health")); assertTrue(layerIterator.next() == result.getLayer("enemies")); assertTrue(layerIterator.next() == result.getLayer("bullet")); } catch (IOException e) { fail(e.getMessage()); } } @Test public void simpleTest() { try { // Load multipolygon z0 tile final JtsMvt mvt = loadMvt("src/test/resources/vec_tile_test/0/0/0.mvt"); List<Geometry> geoms = getAllGeometries(mvt); // Debug stats of multipolygon final JtsGeomStats stats = JtsGeomStats.getStats(geoms); LoggerFactory.getLogger(MvtReaderTest.class).info("Stats: {}", stats); } catch (IOException e) { fail(e.getMessage()); } } @Test public void testNegExtPolyRings() { try { // Single MultiPolygon with two triangles that have negative area from shoelace formula // Support for 'V1' MVTs. final JtsMvt mvt = loadMvt( "src/test/resources/mapbox/vector_tile_js/multi_poly_neg_exters.mvt", MvtReader.RING_CLASSIFIER_V1); final List<Geometry> geoms = getAllGeometries(mvt); assertEquals(1, geoms.size()); assertTrue(geoms.get(0) instanceof MultiPolygon); final MultiPolygon multiPolygon = (MultiPolygon) geoms.get(0); assertEquals(2, multiPolygon.getNumGeometries()); { final Polygon polygon = (Polygon) multiPolygon.getGeometryN(0); assertEquals(0, polygon.getNumInteriorRing()); final LineString exteriorRing = polygon.getExteriorRing(); assertEquals(4, exteriorRing.getNumPoints()); assertEquals(2059.0, exteriorRing.getCoordinateN(0).x, DOUBLE_DELTA); assertEquals(2048.0, exteriorRing.getCoordinateN(0).y, DOUBLE_DELTA); assertEquals(2048.0, exteriorRing.getCoordinateN(1).x, DOUBLE_DELTA); assertEquals(2048.0, exteriorRing.getCoordinateN(1).y, DOUBLE_DELTA); assertEquals(2059.0, exteriorRing.getCoordinateN(2).x, DOUBLE_DELTA); assertEquals(2037.0, exteriorRing.getCoordinateN(2).y, DOUBLE_DELTA); assertEquals(2059.0, exteriorRing.getCoordinateN(3).x, DOUBLE_DELTA); assertEquals(2048.0, exteriorRing.getCoordinateN(3).y, DOUBLE_DELTA); } { final Polygon polygon = (Polygon) multiPolygon.getGeometryN(1); assertEquals(0, polygon.getNumInteriorRing()); final LineString exteriorRing = polygon.getExteriorRing(); assertEquals(4, exteriorRing.getNumPoints()); assertEquals(2037.0, exteriorRing.getCoordinateN(0).x, DOUBLE_DELTA); assertEquals(2059.0, exteriorRing.getCoordinateN(0).y, DOUBLE_DELTA); assertEquals(2037.0, exteriorRing.getCoordinateN(1).x, DOUBLE_DELTA); assertEquals(2048.0, exteriorRing.getCoordinateN(1).y, DOUBLE_DELTA); assertEquals(2048.0, exteriorRing.getCoordinateN(2).x, DOUBLE_DELTA); assertEquals(2048.0, exteriorRing.getCoordinateN(2).y, DOUBLE_DELTA); assertEquals(2037.0, exteriorRing.getCoordinateN(3).x, DOUBLE_DELTA); assertEquals(2059.0, exteriorRing.getCoordinateN(3).y, DOUBLE_DELTA); } } catch (IOException e) { fail(e.getMessage()); } } private List<Geometry> getAllGeometries(JtsMvt mvt) { List<Geometry> allGeoms = new ArrayList<>(); for (JtsLayer l : mvt.getLayers()) { allGeoms.addAll(l.getGeometries()); } return allGeoms; } private static JtsMvt loadMvt(String file) throws IOException { return MvtReader.loadMvt( new File(file), createGeometryFactory(), new TagKeyValueMapConverter()); } private static JtsMvt loadMvt(String file, MvtReader.RingClassifier ringClassifier) throws IOException { return MvtReader.loadMvt( new File(file), createGeometryFactory(), new TagKeyValueMapConverter(), ringClassifier); } private static GeometryFactory createGeometryFactory() { final PrecisionModel precisionModel = new PrecisionModel(); final PackedCoordinateSequenceFactory coordinateSequenceFactory = new PackedCoordinateSequenceFactory(PackedCoordinateSequenceFactory.DOUBLE, NUMBER_OF_DIMENSIONS); return new GeometryFactory(precisionModel, SRID, coordinateSequenceFactory); } }