private void updateTileBounds(TileMatrixSet tileMatrixSet)
			throws SQLException {

		TileDao tileDao = geoPackage.getTileDao(tileMatrixSet);

		if (tileDao.isGoogleTiles()) {
			if (!googleTiles) {
				// If adding GeoPackage tiles to a Google Tile format, add them
				// as Google tiles
				googleTiles = true;
				adjustGoogleBounds();
			}
		} else if (googleTiles) {
			// Can't add Google formatted tiles to GeoPackage tiles
			throw new GeoPackageException(
					"Can not add Google formatted tiles to "
							+ tableName
							+ " which already contains GeoPackage formatted tiles");
		}

		Projection tileMatrixProjection = tileMatrixSet.getSrs()
				.getProjection();
		if (!tileMatrixProjection.equals(projection)) {
			throw new GeoPackageException("Can not update tiles projected at "
					+ tileMatrixProjection.getCode()
					+ " with tiles projected at " + projection.getCode());
		}

		Contents contents = tileMatrixSet.getContents();

		// Combine the existing content and request bounding boxes
		BoundingBox previousContentsBoundingBox = contents.getBoundingBox();
		if (previousContentsBoundingBox != null) {
			ProjectionTransform transformProjectionToContents = projection
					.getTransformation(contents.getProjection());
			BoundingBox contentsBoundingBox = boundingBox;
			if (!transformProjectionToContents.isSameProjection()) {
				contentsBoundingBox = contentsBoundingBox
						.transform(transformProjectionToContents);
			}
			contentsBoundingBox = contentsBoundingBox
					.union(previousContentsBoundingBox);

			// Update the contents if modified
			if (!contentsBoundingBox.equals(previousContentsBoundingBox)) {
				contents.setBoundingBox(contentsBoundingBox);
				ContentsDao contentsDao = geoPackage.getContentsDao();
				contentsDao.update(contents);
			}
		}

		// If updating GeoPackage format tiles, all existing metadata and tile
		// rows needs to be adjusted
		if (!googleTiles) {

			BoundingBox previousTileMatrixSetBoundingBox = tileMatrixSet
					.getBoundingBox();

			// Adjust the bounds to include the request and existing bounds
			ProjectionTransform transformProjectionToTileMatrixSet = projection
					.getTransformation(tileMatrixProjection);
			boolean sameProjection = transformProjectionToTileMatrixSet
					.isSameProjection();
			BoundingBox updateBoundingBox = tileBounds.get(minZoom);
			if (!sameProjection) {
				updateBoundingBox = updateBoundingBox
						.transform(transformProjectionToTileMatrixSet);
			}
			int minNewOrUpdateZoom = Math.min(minZoom,
					(int) tileDao.getMinZoom());
			adjustBounds(updateBoundingBox, minNewOrUpdateZoom);

			// Update the tile matrix set if modified
			BoundingBox updateTileGridBoundingBox = tileGridBoundingBox;
			if (!sameProjection) {
				updateTileGridBoundingBox = updateTileGridBoundingBox
						.transform(transformProjectionToTileMatrixSet);
			}
			if (!previousTileMatrixSetBoundingBox
					.equals(updateTileGridBoundingBox)) {
				updateTileGridBoundingBox = updateTileGridBoundingBox
						.union(previousTileMatrixSetBoundingBox);
				adjustBounds(updateTileGridBoundingBox, minNewOrUpdateZoom);
				updateTileGridBoundingBox = tileGridBoundingBox;
				if (!sameProjection) {
					updateTileGridBoundingBox = updateTileGridBoundingBox
							.transform(transformProjectionToTileMatrixSet);
				}
				tileMatrixSet.setBoundingBox(updateTileGridBoundingBox);
				TileMatrixSetDao tileMatrixSetDao = geoPackage
						.getTileMatrixSetDao();
				tileMatrixSetDao.update(tileMatrixSet);
			}

			TileMatrixDao tileMatrixDao = geoPackage.getTileMatrixDao();

			// Adjust the tile matrix metadata and tile rows at each existing
			// zoom level
			for (long zoom = tileDao.getMinZoom(); zoom <= tileDao.getMaxZoom(); zoom++) {
				TileMatrix tileMatrix = tileDao.getTileMatrix(zoom);
				if (tileMatrix != null) {

					// Determine the new width and height at this level
					long adjustment = (long) Math.pow(2, zoom
							- minNewOrUpdateZoom);
					long zoomMatrixWidth = matrixWidth * adjustment;
					long zoomMatrixHeight = matrixHeight * adjustment;

					// Get the zoom level tile rows, starting with highest rows
					// and columns so when updating we avoid constraint
					// violations
					TileResultSet tileResultSet = tileDao
							.queryForTileDescending(zoom);
					try {
						// Update each tile row at this zoom level
						while (tileResultSet.moveToNext()) {
							TileRow tileRow = tileResultSet.getRow();

							// Get the bounding box of the existing tile
							BoundingBox tileBoundingBox = TileBoundingBoxUtils
									.getBoundingBox(
											previousTileMatrixSetBoundingBox,
											tileMatrix,
											tileRow.getTileColumn(),
											tileRow.getTileRow());

							// Get the mid lat and lon to find the new tile row
							// and column
							double midLatitude = tileBoundingBox
									.getMinLatitude()
									+ ((tileBoundingBox.getMaxLatitude() - tileBoundingBox
											.getMinLatitude()) / 2.0);
							double midLongitude = tileBoundingBox
									.getMinLongitude()
									+ ((tileBoundingBox.getMaxLongitude() - tileBoundingBox
											.getMinLongitude()) / 2.0);

							// Get the new tile row and column with regards to
							// the new bounding box
							long newTileRow = TileBoundingBoxUtils.getTileRow(
									tileGridBoundingBox, zoomMatrixHeight,
									midLatitude);
							long newTileColumn = TileBoundingBoxUtils
									.getTileColumn(tileGridBoundingBox,
											zoomMatrixWidth, midLongitude);

							// Update the tile row
							if (tileRow.getTileRow() != newTileRow
									|| tileRow.getTileColumn() != newTileColumn) {
								tileRow.setTileRow(newTileRow);
								tileRow.setTileColumn(newTileColumn);
								tileDao.update(tileRow);
							}
						}
					} finally {
						tileResultSet.close();
					}

					// Calculate the pixel size
					double pixelXSize = (tileGridBoundingBox.getMaxLongitude() - tileGridBoundingBox
							.getMinLongitude())
							/ zoomMatrixWidth
							/ tileMatrix.getTileWidth();
					double pixelYSize = (tileGridBoundingBox.getMaxLatitude() - tileGridBoundingBox
							.getMinLatitude())
							/ zoomMatrixHeight
							/ tileMatrix.getTileHeight();

					// Update the tile matrix
					tileMatrix.setMatrixWidth(zoomMatrixWidth);
					tileMatrix.setMatrixHeight(zoomMatrixHeight);
					tileMatrix.setPixelXSize(pixelXSize);
					tileMatrix.setPixelYSize(pixelYSize);

					tileMatrixDao.update(tileMatrix);
				}
			}

			// Adjust the width and height to the min zoom level of the
			// request
			if (minNewOrUpdateZoom < minZoom) {
				long adjustment = (long) Math.pow(2, minZoom
						- minNewOrUpdateZoom);
				matrixWidth *= adjustment;
				matrixHeight *= adjustment;
			}

		}
	}
private void updateTileBounds ( TileMatrixSet tileMatrixSet ) throws SQLException { TileDao tileDao = geoPackage . getTileDao ( tileMatrixSet ) ; if ( tileDao . isGoogleTiles ( ) ) { if ( ! googleTiles ) { googleTiles = true ; adjustGoogleBounds ( ) ; } } else if ( googleTiles ) { throw new GeoPackageException ( "Can not add Google formatted tiles to " + tableName + " which already contains GeoPackage formatted tiles" ) ; } Projection tileMatrixProjection = tileMatrixSet . getSrs ( ) . getProjection ( ) ; if ( ! tileMatrixProjection . equals ( projection ) ) { throw new GeoPackageException ( "Can not update tiles projected at " + tileMatrixProjection . getCode ( ) + " with tiles projected at " + projection . getCode ( ) ) ; } Contents contents = tileMatrixSet . getContents ( ) ; BoundingBox previousContentsBoundingBox = contents . getBoundingBox ( ) ; if ( previousContentsBoundingBox != null ) { ProjectionTransform transformProjectionToContents = projection . getTransformation ( contents . getProjection ( ) ) ; BoundingBox contentsBoundingBox = boundingBox ; if ( ! transformProjectionToContents . isSameProjection ( ) ) { contentsBoundingBox = contentsBoundingBox . transform ( transformProjectionToContents ) ; } contentsBoundingBox = contentsBoundingBox . union ( previousContentsBoundingBox ) ; if ( ! contentsBoundingBox . equals ( previousContentsBoundingBox ) ) { contents . setBoundingBox ( contentsBoundingBox ) ; ContentsDao contentsDao = geoPackage . getContentsDao ( ) ; contentsDao . update ( contents ) ; } } if ( ! googleTiles ) { BoundingBox previousTileMatrixSetBoundingBox = tileMatrixSet . getBoundingBox ( ) ; ProjectionTransform transformProjectionToTileMatrixSet = projection . getTransformation ( tileMatrixProjection ) ; boolean sameProjection = transformProjectionToTileMatrixSet . isSameProjection ( ) ; BoundingBox updateBoundingBox = tileBounds . get ( minZoom ) ; if ( ! sameProjection ) { updateBoundingBox = updateBoundingBox . transform ( transformProjectionToTileMatrixSet ) ; } int minNewOrUpdateZoom = Math . min ( minZoom , ( int ) tileDao . getMinZoom ( ) ) ; adjustBounds ( updateBoundingBox , minNewOrUpdateZoom ) ; BoundingBox updateTileGridBoundingBox = tileGridBoundingBox ; if ( ! sameProjection ) { updateTileGridBoundingBox = updateTileGridBoundingBox . transform ( transformProjectionToTileMatrixSet ) ; } if ( ! previousTileMatrixSetBoundingBox . equals ( updateTileGridBoundingBox ) ) { updateTileGridBoundingBox = updateTileGridBoundingBox . union ( previousTileMatrixSetBoundingBox ) ; adjustBounds ( updateTileGridBoundingBox , minNewOrUpdateZoom ) ; updateTileGridBoundingBox = tileGridBoundingBox ; if ( ! sameProjection ) { updateTileGridBoundingBox = updateTileGridBoundingBox . transform ( transformProjectionToTileMatrixSet ) ; } tileMatrixSet . setBoundingBox ( updateTileGridBoundingBox ) ; TileMatrixSetDao tileMatrixSetDao = geoPackage . getTileMatrixSetDao ( ) ; tileMatrixSetDao . update ( tileMatrixSet ) ; } TileMatrixDao tileMatrixDao = geoPackage . getTileMatrixDao ( ) ; for ( long zoom = tileDao . getMinZoom ( ) ; zoom <= tileDao . getMaxZoom ( ) ; zoom ++ ) { TileMatrix tileMatrix = tileDao . getTileMatrix ( zoom ) ; if ( tileMatrix != null ) { long adjustment = ( long ) Math . pow ( 2 , zoom - minNewOrUpdateZoom ) ; long zoomMatrixWidth = matrixWidth * adjustment ; long zoomMatrixHeight = matrixHeight * adjustment ; TileResultSet tileResultSet = tileDao . queryForTileDescending ( zoom ) ; try { while ( tileResultSet . moveToNext ( ) ) { TileRow tileRow = tileResultSet . getRow ( ) ; BoundingBox tileBoundingBox = TileBoundingBoxUtils . getBoundingBox ( previousTileMatrixSetBoundingBox , tileMatrix , tileRow . getTileColumn ( ) , tileRow . getTileRow ( ) ) ; double midLatitude = tileBoundingBox . getMinLatitude ( ) + ( ( tileBoundingBox . getMaxLatitude ( ) - tileBoundingBox . getMinLatitude ( ) ) / 2.0 ) ; double midLongitude = tileBoundingBox . getMinLongitude ( ) + ( ( tileBoundingBox . getMaxLongitude ( ) - tileBoundingBox . getMinLongitude ( ) ) / 2.0 ) ; long newTileRow = TileBoundingBoxUtils . getTileRow ( tileGridBoundingBox , zoomMatrixHeight , midLatitude ) ; long newTileColumn = TileBoundingBoxUtils . getTileColumn ( tileGridBoundingBox , zoomMatrixWidth , midLongitude ) ; if ( tileRow . getTileRow ( ) != newTileRow || tileRow . getTileColumn ( ) != newTileColumn ) { tileRow . setTileRow ( newTileRow ) ; tileRow . setTileColumn ( newTileColumn ) ; tileDao . update ( tileRow ) ; } } } finally { tileResultSet . close ( ) ; } double pixelXSize = ( tileGridBoundingBox . getMaxLongitude ( ) - tileGridBoundingBox . getMinLongitude ( ) ) / zoomMatrixWidth / tileMatrix . getTileWidth ( ) ; double pixelYSize = ( tileGridBoundingBox . getMaxLatitude ( ) - tileGridBoundingBox . getMinLatitude ( ) ) / zoomMatrixHeight / tileMatrix . getTileHeight ( ) ; tileMatrix . setMatrixWidth ( zoomMatrixWidth ) ; tileMatrix . setMatrixHeight ( zoomMatrixHeight ) ; tileMatrix . setPixelXSize ( pixelXSize ) ; tileMatrix . setPixelYSize ( pixelYSize ) ; tileMatrixDao . update ( tileMatrix ) ; } } if ( minNewOrUpdateZoom < minZoom ) { long adjustment = ( long ) Math . pow ( 2 , minZoom - minNewOrUpdateZoom ) ; matrixWidth *= adjustment ; matrixHeight *= adjustment ; } } }
Update the Content and Tile Matrix Set bounds

@param tileMatrixSet
@throws java.sql.SQLException