package mil.nga.geopackage.test.tiles; import java.awt.image.BufferedImage; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; import java.sql.SQLException; import junit.framework.TestCase; import mil.nga.geopackage.BoundingBox; import mil.nga.geopackage.GeoPackage; import mil.nga.geopackage.test.TestUtils; import mil.nga.geopackage.test.io.TestGeoPackageProgress; import mil.nga.geopackage.tiles.TileBoundingBoxUtils; import mil.nga.geopackage.tiles.TileGenerator; import mil.nga.geopackage.tiles.TileGrid; import mil.nga.geopackage.tiles.UrlTileGenerator; import mil.nga.geopackage.tiles.matrix.TileMatrix; import mil.nga.geopackage.tiles.user.TileDao; import mil.nga.geopackage.tiles.user.TileResultSet; import mil.nga.geopackage.tiles.user.TileRow; import mil.nga.sf.Point; import mil.nga.sf.proj.Projection; import mil.nga.sf.proj.ProjectionConstants; import mil.nga.sf.proj.ProjectionFactory; import org.junit.Assume; /** * URL Tile Generator utils * * @author osbornb */ public class UrlTileGeneratorUtils { private static final String TABLE_NAME = "generate_test"; private static final String BASE_URL = "http://osm.geointservices.io"; private static final String URL = BASE_URL + "/osm_tiles/{z}/{x}/{y}.png"; // private static final String BASE_URL = "http://a.tile.openstreetmap.org"; // private static final String URL = BASE_URL + "/{z}/{x}/{y}.png"; public static void checkUrl() { boolean validConnection = false; try { HttpURLConnection connection = (HttpURLConnection) new URL(BASE_URL) .openConnection(); connection.setRequestMethod("HEAD"); int responseCode = connection.getResponseCode(); validConnection = responseCode != 404; connection.disconnect(); } catch (Exception e) { } Assume.assumeTrue( "Failed to connect to the test url, URL: " + BASE_URL, validConnection); } /** * Test generating tiles * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTiles(GeoPackage geoPackage) throws SQLException, IOException { UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME, URL, 1, 2, getBoundingBox(), getProjection()); testGenerateTiles(tileGenerator); } /** * Test generating tiles with jpeg compression * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTilesCompress(GeoPackage geoPackage) throws SQLException, IOException { UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME, URL, 2, 3, getBoundingBox(), getProjection()); tileGenerator.setCompressFormat("jpeg"); testGenerateTiles(tileGenerator); } /** * Test generating tiles with jpeg compression and quality * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTilesCompressQuality(GeoPackage geoPackage) throws SQLException, IOException { UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME, URL, 0, 1, getBoundingBox(), getProjection()); tileGenerator.setCompressFormat("jpeg"); tileGenerator.setCompressQuality(.7f); testGenerateTiles(tileGenerator); } /** * Test generating tiles in XYZ format * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTilesXYZ(GeoPackage geoPackage) throws SQLException, IOException { UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME, URL, 1, 3, getBoundingBox(), getProjection()); tileGenerator.setXYZTiles(true); testGenerateTiles(tileGenerator); } /** * Test generating tiles with bounding box * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTilesBounded(GeoPackage geoPackage) throws SQLException, IOException { UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME, URL, 1, 2, new BoundingBox(-10, -10, 10, 10), getProjection()); testGenerateTiles(tileGenerator); } /** * Test generating tiles in XYZ format with bounding box * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTilesXYZBounded(GeoPackage geoPackage) throws SQLException, IOException { UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME, URL, 1, 2, new BoundingBox(-10, -10, 10, 10), getProjection()); tileGenerator.setXYZTiles(true); testGenerateTiles(tileGenerator); } /** * Test generating tiles with random bounds and zoomss * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTilesRandom(GeoPackage geoPackage) throws SQLException, IOException { for (int i = 0; i < 10; i++) { int minZoom = (int) (Math.random() * 3.0); int maxZoom = minZoom + ((int) (Math.random() * 3.0)); Point point1 = TestUtils.createPoint(false, false); Point point2 = TestUtils.createPoint(false, false); BoundingBox boundingBox = new BoundingBox(Math.min(point1.getX(), point2.getX()), Math.min(point1.getY(), point2.getY()), Math.max(point1.getX(), point2.getX()), Math.max( point1.getY(), point2.getY())); UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME + i, URL, minZoom, maxZoom, boundingBox, getProjection()); testGenerateTiles(tileGenerator); } } /** * Test generating tiles with unsupported png compression and quality * * @param geoPackage * @throws SQLException * @throws IOException */ public static void testGenerateTilesUnsupportedCompressQuality( GeoPackage geoPackage) throws SQLException, IOException { UrlTileGenerator tileGenerator = new UrlTileGenerator(geoPackage, TABLE_NAME, URL, 0, 1, getBoundingBox(), getProjection()); tileGenerator.setCompressFormat("png"); tileGenerator.setCompressQuality(.7f); int count = tileGenerator.generateTiles(); TestCase.assertEquals(0, count); } private static BoundingBox getBoundingBox() { BoundingBox boundingBox = new BoundingBox(); boundingBox = getBoundingBox(boundingBox); return boundingBox; } private static BoundingBox getBoundingBox(BoundingBox boundingBox) { boundingBox = TileBoundingBoxUtils .boundWgs84BoundingBoxWithWebMercatorLimits(boundingBox); boundingBox = boundingBox.transform(ProjectionFactory.getProjection( ProjectionConstants.EPSG_WORLD_GEODETIC_SYSTEM) .getTransformation(ProjectionConstants.EPSG_WEB_MERCATOR)); return boundingBox; } private static Projection getProjection() { return ProjectionFactory .getProjection(ProjectionConstants.EPSG_WEB_MERCATOR); } /** * Test generating tiles * * @param tileGenerator * @throws SQLException * @throws IOException */ private static void testGenerateTiles(TileGenerator tileGenerator) throws SQLException, IOException { GeoPackage geoPackage = tileGenerator.getGeoPackage(); String tableName = tileGenerator.getTableName(); int minZoom = tileGenerator.getMinZoom(); int maxZoom = tileGenerator.getMaxZoom(); BoundingBox webMercatorBoundingBox = tileGenerator.getBoundingBox(); TestGeoPackageProgress progress = new TestGeoPackageProgress(); tileGenerator.setProgress(progress); int count = tileGenerator.generateTiles(); long expected = expectedTiles(webMercatorBoundingBox, minZoom, maxZoom); TestCase.assertEquals(expected, count); TestCase.assertEquals(expected, progress.getProgress()); TileDao tileDao = geoPackage.getTileDao(tableName); TestCase.assertEquals(expected, tileDao.count()); TestCase.assertEquals(minZoom, tileDao.getMinZoom()); TestCase.assertEquals(maxZoom, tileDao.getMaxZoom()); BoundingBox tileMatrixSetBoundingBox = tileDao.getBoundingBox(); for (int zoom = minZoom; zoom <= maxZoom; zoom++) { TileGrid expectedTileGrid = TileBoundingBoxUtils.getTileGrid( webMercatorBoundingBox, zoom); BoundingBox expectedBoundingBox = TileBoundingBoxUtils .getWebMercatorBoundingBox(expectedTileGrid, zoom); BoundingBox zoomBoundingBox = tileDao.getBoundingBox(zoom); TestCase.assertEquals(expectedBoundingBox.getMinLongitude(), zoomBoundingBox.getMinLongitude(), .000001); TestCase.assertEquals(expectedBoundingBox.getMaxLongitude(), zoomBoundingBox.getMaxLongitude(), .000001); TestCase.assertEquals(expectedBoundingBox.getMinLatitude(), zoomBoundingBox.getMinLatitude(), .000001); TestCase.assertEquals(expectedBoundingBox.getMaxLatitude(), zoomBoundingBox.getMaxLatitude(), .000001); long expectedZoomTiles = expectedTiles(webMercatorBoundingBox, zoom); TestCase.assertEquals(expectedZoomTiles, tileDao.count(zoom)); TileMatrix tileMatrix = tileDao.getTileMatrix(zoom); TileGrid tileGrid = TileBoundingBoxUtils.getTileGrid( tileMatrixSetBoundingBox, tileMatrix.getMatrixWidth(), tileMatrix.getMatrixHeight(), zoomBoundingBox); TestCase.assertTrue(tileGrid.getMinX() >= 0); TestCase.assertTrue(tileGrid.getMaxX() < tileMatrix .getMatrixWidth()); TestCase.assertTrue(tileGrid.getMinY() >= 0); TestCase.assertTrue(tileGrid.getMaxY() < tileMatrix .getMatrixHeight()); TileResultSet resultSet = tileDao.queryForTile(zoom); TestCase.assertEquals(expectedZoomTiles, resultSet.getCount()); int resultCount = 0; while (resultSet.moveToNext()) { TileRow tileRow = resultSet.getRow(); resultCount++; byte[] tileData = tileRow.getTileData(); TestCase.assertNotNull(tileData); BufferedImage image = tileRow.getTileDataImage(); TestCase.assertNotNull(image); TestCase.assertEquals(tileMatrix.getTileWidth(), image.getWidth()); TestCase.assertEquals(tileMatrix.getTileHeight(), image.getHeight()); } TestCase.assertEquals(expectedZoomTiles, resultCount); } } /** * Expected number of XYZ tiles between zoom range and bounding box * * @param webMercatorBoundingBox * @param minZoom * @param maxZoom * @return */ private static long expectedTiles(BoundingBox webMercatorBoundingBox, int minZoom, int maxZoom) { long tiles = 0; for (int zoom = minZoom; zoom <= maxZoom; zoom++) { tiles += expectedTiles(webMercatorBoundingBox, zoom); } return tiles; } /** * Expected number of XYZ tiles at zoom and bounding box * * @param webMercatorBoundingBox * @param zoom * @return */ private static long expectedTiles(BoundingBox webMercatorBoundingBox, int zoom) { TileGrid tileGrid = TileBoundingBoxUtils.getTileGrid( webMercatorBoundingBox, zoom); return tileGrid.count(); } }