Input: Manually count the rows within the bounding box in the provided projection [CODESPLIT] public long count ( BoundingBox boundingBox , Projection projection ) { BoundingBox featureBoundingBox = featureDao . projectBoundingBox ( boundingBox , projection ) ; return count ( featureBoundingBox ) ; }


Input: Manually query for rows within the geometry envelope [CODESPLIT] public ManualFeatureQueryResults query ( GeometryEnvelope envelope ) { return query ( envelope . getMinX ( ) , envelope . getMinY ( ) , envelope . getMaxX ( ) , envelope . getMaxY ( ) ) ; }


Input: Manually query for rows within the bounds [CODESPLIT] public ManualFeatureQueryResults query ( double minX , double minY , double maxX , double maxY ) { List < Long > featureIds = new ArrayList <> ( ) ; long offset = 0 ; boolean hasResults = true ; minX -= tolerance ; maxX += tolerance ; minY -= tolerance ; maxY += tolerance ; while ( hasResults ) { hasResults = false ; FeatureCursor featureCursor = featureDao . queryForChunk ( chunkLimit , offset ) ; try { while ( featureCursor . moveToNext ( ) ) { hasResults = true ; FeatureRow featureRow = featureCursor . getRow ( ) ; GeometryEnvelope envelope = featureRow . getGeometryEnvelope ( ) ; if ( envelope != null ) { double minXMax = Math . max ( minX , envelope . getMinX ( ) ) ; double maxXMin = Math . min ( maxX , envelope . getMaxX ( ) ) ; double minYMax = Math . max ( minY , envelope . getMinY ( ) ) ; double maxYMin = Math . min ( maxY , envelope . getMaxY ( ) ) ; if ( minXMax <= maxXMin && minYMax <= maxYMin ) { featureIds . add ( featureRow . getId ( ) ) ; } } } } finally { featureCursor . close ( ) ; } offset += chunkLimit ; } ManualFeatureQueryResults results = new ManualFeatureQueryResults ( featureDao , featureIds ) ; return results ; }


Input: Manually count the rows within the bounds [CODESPLIT] public long count ( double minX , double minY , double maxX , double maxY ) { return query ( minX , minY , maxX , maxY ) . count ( ) ; }


Input:
{ [CODESPLIT] @ Override public Iterator < FeatureRow > iterator ( ) { return new Iterator < FeatureRow > ( ) { /**
             * {@inheritDoc}
             */ @ Override public boolean hasNext ( ) { return cursor . moveToNext ( ) ; } /**
             * {@inheritDoc}
             */ @ Override public FeatureRow next ( ) { return cursor . getRow ( ) ; } } ; }


Input: Read the data bounds without allocating pixel memory . Access values using : { @link BitmapFactory . Options#outWidth } { @link BitmapFactory . Options#outHeight } { @link BitmapFactory . Options#outMimeType } { @link BitmapFactory . Options#outColorSpace } and { @link BitmapFactory . Options#outConfig } [CODESPLIT] public BitmapFactory . Options getDataBounds ( ) { BitmapFactory . Options options = new BitmapFactory . Options ( ) ; options . inJustDecodeBounds = true ; byte [ ] data = getData ( ) ; BitmapFactory . decodeByteArray ( data , 0 , data . length , options ) ; return options ; }


Input: Set the data from a full quality bitmap [CODESPLIT] public void setData ( Bitmap bitmap , Bitmap . CompressFormat format ) throws IOException { setData ( bitmap , format , 100 ) ; }


Input: Set the data from a bitmap [CODESPLIT] public void setData ( Bitmap bitmap , Bitmap . CompressFormat format , int quality ) throws IOException { setData ( BitmapConverter . toBytes ( bitmap , format , quality ) ) ; }


Input: Set the Bitmap Compress Config [CODESPLIT] public void setBitmapCompressionConfig ( Config config ) { if ( options == null ) { options = new Options ( ) ; } options . inPreferredConfig = config ; }


Input: Get the tile count of tiles to be generated [CODESPLIT] public int getTileCount ( ) { if ( tileCount == null ) { long count = 0 ; boolean degrees = projection . isUnit ( Units . DEGREES ) ; ProjectionTransform transformToWebMercator = null ; if ( ! degrees ) { transformToWebMercator = projection . getTransformation ( ProjectionConstants . EPSG_WEB_MERCATOR ) ; } for ( int zoom = minZoom ; zoom <= maxZoom ; zoom ++ ) { BoundingBox expandedBoundingBox = getBoundingBox ( zoom ) ; // Get the tile grid that includes the entire bounding box TileGrid tileGrid = null ; if ( degrees ) { tileGrid = TileBoundingBoxUtils . getTileGridWGS84 ( expandedBoundingBox , zoom ) ; } else { tileGrid = TileBoundingBoxUtils . getTileGrid ( expandedBoundingBox . transform ( transformToWebMercator ) , zoom ) ; } count += tileGrid . count ( ) ; tileGrids . put ( zoom , tileGrid ) ; tileBounds . put ( zoom , expandedBoundingBox ) ; } tileCount = ( int ) Math . min ( count , Integer . MAX_VALUE ) ; } return tileCount ; }


Input: Adjust the tile matrix set and bounds [CODESPLIT] private void adjustBounds ( BoundingBox boundingBox , int zoom ) { // Google Tile Format if ( googleTiles ) { adjustGoogleBounds ( ) ; } else if ( projection . isUnit ( Units . DEGREES ) ) { adjustGeoPackageBoundsWGS84 ( boundingBox , zoom ) ; } else { adjustGeoPackageBounds ( boundingBox , zoom ) ; } }


Input: Adjust the tile matrix set and web mercator bounds for Google tile format [CODESPLIT] private void adjustGoogleBounds ( ) { // Set the tile matrix set bounding box to be the world BoundingBox standardWgs84Box = new BoundingBox ( - ProjectionConstants . WGS84_HALF_WORLD_LON_WIDTH , ProjectionConstants . WEB_MERCATOR_MIN_LAT_RANGE , ProjectionConstants . WGS84_HALF_WORLD_LON_WIDTH , ProjectionConstants . WEB_MERCATOR_MAX_LAT_RANGE ) ; ProjectionTransform wgs84ToWebMercatorTransform = ProjectionFactory . getProjection ( ProjectionConstants . EPSG_WORLD_GEODETIC_SYSTEM ) . getTransformation ( ProjectionConstants . EPSG_WEB_MERCATOR ) ; tileGridBoundingBox = standardWgs84Box . transform ( wgs84ToWebMercatorTransform ) ; }


Input: Adjust the tile matrix set and WGS84 bounds for GeoPackage format . Determine the tile grid width and height [CODESPLIT] private void adjustGeoPackageBoundsWGS84 ( BoundingBox boundingBox , int zoom ) { // Get the fitting tile grid and determine the bounding box that fits it TileGrid tileGrid = TileBoundingBoxUtils . getTileGridWGS84 ( boundingBox , zoom ) ; tileGridBoundingBox = TileBoundingBoxUtils . getWGS84BoundingBox ( tileGrid , zoom ) ; matrixWidth = tileGrid . getMaxX ( ) + 1 - tileGrid . getMinX ( ) ; matrixHeight = tileGrid . getMaxY ( ) + 1 - tileGrid . getMinY ( ) ; }


Input: Adjust the tile matrix set and web mercator bounds for GeoPackage format . Determine the tile grid width and height [CODESPLIT] private void adjustGeoPackageBounds ( BoundingBox requestWebMercatorBoundingBox , int zoom ) { // Get the fitting tile grid and determine the bounding box that // fits it TileGrid tileGrid = TileBoundingBoxUtils . getTileGrid ( requestWebMercatorBoundingBox , zoom ) ; tileGridBoundingBox = TileBoundingBoxUtils . getWebMercatorBoundingBox ( tileGrid , zoom ) ; matrixWidth = tileGrid . getMaxX ( ) + 1 - tileGrid . getMinX ( ) ; matrixHeight = tileGrid . getMaxY ( ) + 1 - tileGrid . getMinY ( ) ; }


Input: Get the bounding box of tiles [CODESPLIT] public BoundingBox getBoundingBox ( long zoomLevel ) { BoundingBox boundingBox = null ; TileMatrix tileMatrix = getTileMatrix ( zoomLevel ) ; if ( tileMatrix != null ) { TileGrid tileGrid = queryForTileGrid ( zoomLevel ) ; if ( tileGrid != null ) { BoundingBox matrixSetBoundingBox = getBoundingBox ( ) ; boundingBox = TileBoundingBoxUtils . getBoundingBox ( matrixSetBoundingBox , tileMatrix , tileGrid ) ; } } return boundingBox ; }


Input: Get the tile grid of the zoom level [CODESPLIT] public TileGrid getTileGrid ( long zoomLevel ) { TileGrid tileGrid = null ; TileMatrix tileMatrix = getTileMatrix ( zoomLevel ) ; if ( tileMatrix != null ) { tileGrid = new TileGrid ( 0 , 0 , tileMatrix . getMatrixWidth ( ) - 1 , tileMatrix . getMatrixHeight ( ) - 1 ) ; } return tileGrid ; }


Input: Query for a Tile [CODESPLIT] public TileRow queryForTile ( long column , long row , long zoomLevel ) { Map < String , Object > fieldValues = new HashMap < String , Object > ( ) ; fieldValues . put ( TileTable . COLUMN_TILE_COLUMN , column ) ; fieldValues . put ( TileTable . COLUMN_TILE_ROW , row ) ; fieldValues . put ( TileTable . COLUMN_ZOOM_LEVEL , zoomLevel ) ; TileCursor cursor = queryForFieldValues ( fieldValues ) ; TileRow tileRow = null ; try { if ( cursor . moveToNext ( ) ) { tileRow = cursor . getRow ( ) ; } } finally { cursor . close ( ) ; } return tileRow ; }


Input: Query for Tiles at a zoom level in descending row and column order [CODESPLIT] public TileCursor queryForTileDescending ( long zoomLevel ) { return queryForEq ( TileTable . COLUMN_ZOOM_LEVEL , zoomLevel , null , null , TileTable . COLUMN_TILE_ROW + " DESC, " + TileTable . COLUMN_TILE_COLUMN + " DESC" ) ; }


Input: Get the zoom level for the provided width and height in the default units [CODESPLIT] public Long getZoomLevel ( double length ) { Long zoomLevel = TileDaoUtils . getZoomLevel ( widths , heights , tileMatrices , length ) ; return zoomLevel ; }


Input: Get the zoom level for the provided width and height in the default units [CODESPLIT] public Long getZoomLevel ( double width , double height ) { Long zoomLevel = TileDaoUtils . getZoomLevel ( widths , heights , tileMatrices , width , height ) ; return zoomLevel ; }


Input: Get the closest zoom level for the provided width and height in the default units [CODESPLIT] public Long getClosestZoomLevel ( double length ) { Long zoomLevel = TileDaoUtils . getClosestZoomLevel ( widths , heights , tileMatrices , length ) ; return zoomLevel ; }


Input: Get the approximate zoom level for the provided length in the default units . Tiles may or may not exist for the returned zoom level . The approximate zoom level is determined using a factor of 2 from the zoom levels with tiles . [CODESPLIT] public Long getApproximateZoomLevel ( double length ) { Long zoomLevel = TileDaoUtils . getApproximateZoomLevel ( widths , heights , tileMatrices , length ) ; return zoomLevel ; }


Input: Query for the bounding [CODESPLIT] public TileGrid queryForTileGrid ( long zoomLevel ) { String where = buildWhere ( TileTable . COLUMN_ZOOM_LEVEL , zoomLevel ) ; String [ ] whereArgs = buildWhereArgs ( new Object [ ] { zoomLevel } ) ; Integer minX = min ( TileTable . COLUMN_TILE_COLUMN , where , whereArgs ) ; Integer maxX = max ( TileTable . COLUMN_TILE_COLUMN , where , whereArgs ) ; Integer minY = min ( TileTable . COLUMN_TILE_ROW , where , whereArgs ) ; Integer maxY = max ( TileTable . COLUMN_TILE_ROW , where , whereArgs ) ; TileGrid tileGrid = null ; if ( minX != null && maxX != null && minY != null && maxY != null ) { tileGrid = new TileGrid ( minX , minY , maxX , maxY ) ; } return tileGrid ; }


Input: Delete a Tile [CODESPLIT] public int deleteTile ( long column , long row , long zoomLevel ) { StringBuilder where = new StringBuilder ( ) ; where . append ( buildWhere ( TileTable . COLUMN_ZOOM_LEVEL , zoomLevel ) ) ; where . append ( " AND " ) ; where . append ( buildWhere ( TileTable . COLUMN_TILE_COLUMN , column ) ) ; where . append ( " AND " ) ; where . append ( buildWhere ( TileTable . COLUMN_TILE_ROW , row ) ) ; String [ ] whereArgs = buildWhereArgs ( new Object [ ] { zoomLevel , column , row } ) ; int deleted = delete ( where . toString ( ) , whereArgs ) ; return deleted ; }


Input: Count of Tiles at a zoom level [CODESPLIT] public int count ( long zoomLevel ) { String where = buildWhere ( TileTable . COLUMN_ZOOM_LEVEL , zoomLevel ) ; String [ ] whereArgs = buildWhereArgs ( zoomLevel ) ; return count ( where , whereArgs ) ; }


Input: Determine if the tiles are in the Google tile coordinate format [CODESPLIT] public boolean isGoogleTiles ( ) { // Convert the bounding box to wgs84 BoundingBox boundingBox = tileMatrixSet . getBoundingBox ( ) ; BoundingBox wgs84BoundingBox = boundingBox . transform ( projection . getTransformation ( ProjectionConstants . EPSG_WORLD_GEODETIC_SYSTEM ) ) ; boolean googleTiles = false ; // Verify the bounds are the entire world if ( wgs84BoundingBox . getMinLatitude ( ) <= ProjectionConstants . WEB_MERCATOR_MIN_LAT_RANGE && wgs84BoundingBox . getMaxLatitude ( ) >= ProjectionConstants . WEB_MERCATOR_MAX_LAT_RANGE && wgs84BoundingBox . getMinLongitude ( ) <= - ProjectionConstants . WGS84_HALF_WORLD_LON_WIDTH && wgs84BoundingBox . getMaxLongitude ( ) >= ProjectionConstants . WGS84_HALF_WORLD_LON_WIDTH ) { googleTiles = true ; // Verify each tile matrix is the correct width and height for ( TileMatrix tileMatrix : tileMatrices ) { long zoomLevel = tileMatrix . getZoomLevel ( ) ; long tilesPerSide = TileBoundingBoxUtils . tilesPerSide ( ( int ) zoomLevel ) ; if ( tileMatrix . getMatrixWidth ( ) != tilesPerSide || tileMatrix . getMatrixHeight ( ) != tilesPerSide ) { googleTiles = false ; break ; } } } return googleTiles ; }


Input: { [CODESPLIT] @ Override public Double getValue ( GriddedTile griddedTile , CoverageDataTiffImage image , int x , int y ) { Double value = null ; if ( image . getDirectory ( ) != null ) { float pixelValue = image . getPixel ( x , y ) ; value = getValue ( griddedTile , pixelValue ) ; } else { value = getValue ( griddedTile , image . getImageBytes ( ) , x , y ) ; } return value ; }


Input: Get the pixel value as a float from the image and the coordinate [CODESPLIT] public float getPixelValue ( byte [ ] imageBytes , int x , int y ) { TIFFImage tiffImage = TiffReader . readTiff ( imageBytes ) ; FileDirectory directory = tiffImage . getFileDirectory ( ) ; validateImageType ( directory ) ; Rasters rasters = directory . readRasters ( ) ; float pixelValue = rasters . getFirstPixelSample ( x , y ) . floatValue ( ) ; return pixelValue ; }


Input: Get the pixel values of the image as floats [CODESPLIT] public float [ ] getPixelValues ( byte [ ] imageBytes ) { TIFFImage tiffImage = TiffReader . readTiff ( imageBytes ) ; FileDirectory directory = tiffImage . getFileDirectory ( ) ; validateImageType ( directory ) ; Rasters rasters = directory . readRasters ( ) ; float [ ] pixels = new float [ rasters . getWidth ( ) * rasters . getHeight ( ) ] ; for ( int y = 0 ; y < rasters . getHeight ( ) ; y ++ ) { for ( int x = 0 ; x < rasters . getWidth ( ) ; x ++ ) { int index = rasters . getSampleIndex ( x , y ) ; pixels [ index ] = rasters . getPixelSample ( 0 , x , y ) . floatValue ( ) ; } } return pixels ; }


Input: Validate that the image type [CODESPLIT] public static void validateImageType ( FileDirectory directory ) { if ( directory == null ) { throw new GeoPackageException ( "The image is null" ) ; } int samplesPerPixel = directory . getSamplesPerPixel ( ) ; Integer bitsPerSample = null ; if ( directory . getBitsPerSample ( ) != null && ! directory . getBitsPerSample ( ) . isEmpty ( ) ) { bitsPerSample = directory . getBitsPerSample ( ) . get ( 0 ) ; } Integer sampleFormat = null ; if ( directory . getSampleFormat ( ) != null && ! directory . getSampleFormat ( ) . isEmpty ( ) ) { sampleFormat = directory . getSampleFormat ( ) . get ( 0 ) ; } if ( samplesPerPixel != SAMPLES_PER_PIXEL || bitsPerSample == null || bitsPerSample != BITS_PER_SAMPLE || sampleFormat == null || sampleFormat != TiffConstants . SAMPLE_FORMAT_FLOAT ) { throw new GeoPackageException ( "The coverage data tile is expected to be a single sample 32 bit float. Samples Per Pixel: " + samplesPerPixel + ", Bits Per Sample: " + bitsPerSample + ", Sample Format: " + sampleFormat ) ; } }


Input: { [CODESPLIT] @ Override public Double getValue ( GriddedTile griddedTile , byte [ ] imageBytes , int x , int y ) { float pixelValue = getPixelValue ( imageBytes , x , y ) ; Double value = getValue ( griddedTile , pixelValue ) ; return value ; }


Input: { [CODESPLIT] @ Override public Double [ ] getValues ( GriddedTile griddedTile , byte [ ] imageBytes ) { float [ ] pixelValues = getPixelValues ( imageBytes ) ; Double [ ] values = getValues ( griddedTile , pixelValues ) ; return values ; }


Input: Draw a coverage data image tile from the flat array of float pixel values of length tileWidth * tileHeight where each pixel is at : ( y * tileWidth ) + x [CODESPLIT] public CoverageDataTiffImage drawTile ( float [ ] pixelValues , int tileWidth , int tileHeight ) { CoverageDataTiffImage image = createImage ( tileWidth , tileHeight ) ; for ( int y = 0 ; y < tileHeight ; y ++ ) { for ( int x = 0 ; x < tileWidth ; x ++ ) { float pixelValue = pixelValues [ ( y * tileWidth ) + x ] ; setPixelValue ( image , x , y , pixelValue ) ; } } image . writeTiff ( ) ; return image ; }


Input: Draw a coverage data image tile and format as TIFF bytes from the double array of float pixel values formatted as float [ row ] [ width ] [CODESPLIT] public byte [ ] drawTileData ( float [ ] [ ] pixelValues ) { CoverageDataTiffImage image = drawTile ( pixelValues ) ; byte [ ] bytes = image . getImageBytes ( ) ; return bytes ; }


Input: Draw a coverage data image tile from the flat array of coverage data values of length tileWidth * tileHeight where each coverage data value is at : ( y * tileWidth ) + x [CODESPLIT] public CoverageDataTiffImage drawTile ( GriddedTile griddedTile , Double [ ] values , int tileWidth , int tileHeight ) { CoverageDataTiffImage image = createImage ( tileWidth , tileHeight ) ; for ( int x = 0 ; x < tileWidth ; x ++ ) { for ( int y = 0 ; y < tileHeight ; y ++ ) { Double value = values [ ( y * tileWidth ) + x ] ; float pixelValue = getPixelValue ( griddedTile , value ) ; setPixelValue ( image , x , y , pixelValue ) ; } } image . writeTiff ( ) ; return image ; }


Input: { [CODESPLIT] @ Override public byte [ ] drawTileData ( GriddedTile griddedTile , Double [ ] values , int tileWidth , int tileHeight ) { CoverageDataTiffImage image = drawTile ( griddedTile , values , tileWidth , tileHeight ) ; byte [ ] bytes = image . getImageBytes ( ) ; return bytes ; }


Input: Create a new image [CODESPLIT] public CoverageDataTiffImage createImage ( int tileWidth , int tileHeight ) { Rasters rasters = new Rasters ( tileWidth , tileHeight , 1 , BITS_PER_SAMPLE , TiffConstants . SAMPLE_FORMAT_FLOAT ) ; int rowsPerStrip = rasters . calculateRowsPerStrip ( TiffConstants . PLANAR_CONFIGURATION_CHUNKY ) ; FileDirectory fileDirectory = new FileDirectory ( ) ; fileDirectory . setImageWidth ( tileWidth ) ; fileDirectory . setImageHeight ( tileHeight ) ; fileDirectory . setBitsPerSample ( BITS_PER_SAMPLE ) ; fileDirectory . setCompression ( TiffConstants . COMPRESSION_NO ) ; fileDirectory . setPhotometricInterpretation ( TiffConstants . PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO ) ; fileDirectory . setSamplesPerPixel ( SAMPLES_PER_PIXEL ) ; fileDirectory . setRowsPerStrip ( rowsPerStrip ) ; fileDirectory . setPlanarConfiguration ( TiffConstants . PLANAR_CONFIGURATION_CHUNKY ) ; fileDirectory . setSampleFormat ( TiffConstants . SAMPLE_FORMAT_FLOAT ) ; fileDirectory . setWriteRasters ( rasters ) ; CoverageDataTiffImage image = new CoverageDataTiffImage ( fileDirectory ) ; return image ; }


Input: Set the pixel value into the image [CODESPLIT] public void setPixelValue ( CoverageDataTiffImage image , int x , int y , float pixelValue ) { image . getRasters ( ) . setFirstPixelSample ( x , y , pixelValue ) ; }


Input: Create the coverage data tile table with metadata and extension [CODESPLIT] public static CoverageDataTiff createTileTableWithMetadata ( GeoPackage geoPackage , String tableName , BoundingBox contentsBoundingBox , long contentsSrsId , BoundingBox tileMatrixSetBoundingBox , long tileMatrixSetSrsId ) { CoverageDataTiff coverageData = ( CoverageDataTiff ) CoverageData . createTileTableWithMetadata ( geoPackage , tableName , contentsBoundingBox , contentsSrsId , tileMatrixSetBoundingBox , tileMatrixSetSrsId , GriddedCoverageDataType . FLOAT ) ; return coverageData ; }


Input: Build a JSON compatible object [CODESPLIT] public Object jsonCompatible ( boolean includePoints , boolean includeGeometries ) { Map < String , Object > jsonValues = new HashMap <> ( ) ; for ( String key : values . keySet ( ) ) { Object jsonValue = null ; Object value = values . get ( key ) ; if ( key . equals ( geometryColumn ) ) { GeoPackageGeometryData geometryData = ( GeoPackageGeometryData ) value ; if ( geometryData . getGeometry ( ) != null ) { if ( includeGeometries || ( includePoints && geometryData . getGeometry ( ) . getGeometryType ( ) == GeometryType . POINT ) ) { jsonValue = FeatureConverter . toMap ( geometryData . getGeometry ( ) ) ; } } else { jsonValue = value ; } if ( jsonValue != null ) { jsonValues . put ( key , jsonValue ) ; } } } return jsonValues ; }


Input: Get the cached GeoPackage or open and cache the GeoPackage [CODESPLIT] private GeoPackage getOrOpen ( String name , boolean writable , boolean cache ) { GeoPackage geoPackage = get ( name ) ; if ( geoPackage == null ) { geoPackage = manager . open ( name , writable ) ; if ( cache ) { add ( geoPackage ) ; } } return geoPackage ; }


Input: { [CODESPLIT] @ Override public Object getValue ( TColumn column ) { return getValue ( column . getIndex ( ) , column . getDataType ( ) ) ; }


Input: { [CODESPLIT] @ Override public TRow getRow ( ) { TRow row ; if ( invalidCursor == null ) { row = getCurrentRow ( ) ; } else { row = invalidCursor . getRow ( ) ; } return row ; }


Input: Get the current row [CODESPLIT] private TRow getCurrentRow ( ) { TRow row = null ; if ( table != null ) { int [ ] columnTypes = new int [ table . columnCount ( ) ] ; Object [ ] values = new Object [ table . columnCount ( ) ] ; boolean valid = true ; for ( TColumn column : table . getColumns ( ) ) { int index = column . getIndex ( ) ; int columnType = getType ( index ) ; if ( column . isPrimaryKey ( ) && columnType == FIELD_TYPE_NULL ) { valid = false ; } columnTypes [ index ] = columnType ; values [ index ] = getValue ( column ) ; } row = getRow ( columnTypes , values ) ; if ( ! valid ) { invalidPositions . add ( getPosition ( ) ) ; row . setValid ( false ) ; } } return row ; }


Input: { [CODESPLIT] @ Override public Object getValue ( int index , GeoPackageDataType dataType ) { return ResultUtils . getValue ( invalidCursor == null ? this : invalidCursor , index , dataType ) ; }


Input: Enable requery attempt of invalid rows after iterating through original query rows . Only supported for { @link #moveToNext () } and { @link #getRow () } usage . [CODESPLIT] protected void enableInvalidRequery ( UserDao < TColumn , TTable , TRow , ? extends UserCursor < TColumn , TTable , TRow > > dao ) { this . dao = dao ; }


Input: Move to the next position of invalid rows to requery . Perform the requery the first time . [CODESPLIT] private boolean moveToNextInvalid ( ) { boolean hasNext = false ; // If requery has not been performed, a requery dao has been set, and there are invalid positions if ( invalidCursor == null && dao != null && hasInvalidPositions ( ) ) { // Close the original cursor when performing an invalid cursor query super . close ( ) ; // Set the blob columns to return as null List < TColumn > blobColumns = dao . getTable ( ) . columnsOfType ( GeoPackageDataType . BLOB ) ; String [ ] columnsAs = dao . buildColumnsAsNull ( blobColumns ) ; query . set ( UserQueryParamType . COLUMNS_AS , columnsAs ) ; // Query without blob columns and create an invalid cursor UserCursor < TColumn , TTable , TRow > requeryCursor = dao . query ( query ) ; invalidCursor = createInvalidCursor ( dao , requeryCursor , getInvalidPositions ( ) , blobColumns ) ; } if ( invalidCursor != null ) { hasNext = invalidCursor . moveToNext ( ) ; } return hasNext ; }


Input: { [CODESPLIT] @ Override public BoundingBox getBoundingBox ( Projection projection ) { Contents contents = geometryColumns . getContents ( ) ; BoundingBox boundingBox = contents . getBoundingBox ( projection ) ; return boundingBox ; }


Input: Build a JSON compatible object [CODESPLIT] public Object jsonCompatible ( boolean includePoints , boolean includeGeometries ) { Object jsonObject = null ; if ( rows == null || rows . isEmpty ( ) ) { jsonObject = count ; } else { List < Object > jsonRows = new ArrayList <> ( ) ; for ( FeatureRowData row : rows ) { jsonRows . add ( row . jsonCompatible ( includePoints , includeGeometries ) ) ; } jsonObject = jsonRows ; } return jsonObject ; }


Input: Query for style mappings by base id [CODESPLIT] public List < StyleMappingRow > queryByBaseFeatureId ( long id ) { List < StyleMappingRow > rows = new ArrayList <> ( ) ; UserCustomCursor cursor = queryByBaseId ( id ) ; try { while ( cursor . moveToNext ( ) ) { rows . add ( getRow ( cursor ) ) ; } } finally { cursor . close ( ) ; } return rows ; }


Input: Delete by base is and geometry type [CODESPLIT] public int deleteByBaseId ( long id , GeometryType geometryType ) { String geometryTypeName = null ; if ( geometryType != null ) { geometryTypeName = geometryType . getName ( ) ; } StringBuilder where = new StringBuilder ( ) ; where . append ( buildWhere ( StyleMappingTable . COLUMN_BASE_ID , id ) ) ; where . append ( " AND " ) ; where . append ( buildWhere ( StyleMappingTable . COLUMN_GEOMETRY_TYPE_NAME , geometryTypeName ) ) ; List < Object > whereArguments = new ArrayList <> ( ) ; whereArguments . add ( id ) ; if ( geometryTypeName != null ) { whereArguments . add ( geometryTypeName ) ; } String [ ] whereArgs = buildWhereArgs ( whereArguments ) ; int deleted = delete ( where . toString ( ) , whereArgs ) ; return deleted ; }


Input: Get a rectangle using the tile width height bounding box and the bounding box section within the outer box to build the rectangle from [CODESPLIT] public static Rect getRectangle ( long width , long height , BoundingBox boundingBox , BoundingBox boundingBoxSection ) { RectF rectF = getFloatRectangle ( width , height , boundingBox , boundingBoxSection ) ; Rect rect = new Rect ( Math . round ( rectF . left ) , Math . round ( rectF . top ) , Math . round ( rectF . right ) , Math . round ( rectF . bottom ) ) ; return rect ; }


Input: Get a rectangle with rounded floating point boundaries using the tile width height bounding box and the bounding box section within the outer box to build the rectangle from [CODESPLIT] public static RectF getRoundedFloatRectangle ( long width , long height , BoundingBox boundingBox , BoundingBox boundingBoxSection ) { Rect rect = getRectangle ( width , height , boundingBox , boundingBoxSection ) ; RectF rectF = new RectF ( rect ) ; return rectF ; }


Input: Check if the rectangle is valid [CODESPLIT] public static boolean isValid ( Rect rect ) { return rect . left < rect . right && rect . top < rect . bottom ; }


Input: Check if the rectangle is valid allowing empty ranges [CODESPLIT] public static boolean isValidAllowEmpty ( Rect rect ) { return rect . left <= rect . right && rect . top <= rect . bottom ; }


Input: Check if the rectangle is valid [CODESPLIT] public static boolean isValid ( RectF rectF ) { return rectF . left < rectF . right && rectF . top < rectF . bottom ; }


Input: Check if the rectangle is valid allowing empty ranges [CODESPLIT] public static boolean isValidAllowEmpty ( RectF rectF ) { return rectF . left <= rectF . right && rectF . top <= rectF . bottom ; }


Input: { [CODESPLIT] @ Override public List < String > databases ( ) { Set < String > sortedDatabases = new TreeSet < String > ( ) ; addDatabases ( sortedDatabases ) ; List < String > databases = new ArrayList < String > ( ) ; databases . addAll ( sortedDatabases ) ; return databases ; }


Input: { [CODESPLIT] @ Override public List < String > databasesLike ( String like ) { List < String > databases = null ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; databases = dataSource . getMetadataWhereNameLike ( like , GeoPackageMetadata . COLUMN_NAME ) ; } finally { metadataDb . close ( ) ; } databases = deleteMissingDatabases ( databases ) ; return databases ; }


Input: { [CODESPLIT] @ Override public List < String > databasesNotLike ( String notLike ) { List < String > databases = null ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; databases = dataSource . getMetadataWhereNameNotLike ( notLike , GeoPackageMetadata . COLUMN_NAME ) ; } finally { metadataDb . close ( ) ; } databases = deleteMissingDatabases ( databases ) ; return databases ; }


Input: Delete all databases that do not exist or the database file does not exist [CODESPLIT] private List < String > deleteMissingDatabases ( List < String > databases ) { List < String > filesExist = new ArrayList <> ( ) ; for ( String database : databases ) { if ( exists ( database ) ) { filesExist . add ( database ) ; } } return filesExist ; }


Input: { [CODESPLIT] @ Override public List < String > internalDatabases ( ) { Set < String > sortedDatabases = new TreeSet < String > ( ) ; addInternalDatabases ( sortedDatabases ) ; List < String > databases = new ArrayList < String > ( ) ; databases . addAll ( sortedDatabases ) ; return databases ; }


Input: { [CODESPLIT] @ Override public List < String > externalDatabases ( ) { Set < String > sortedDatabases = new TreeSet < String > ( ) ; addExternalDatabases ( sortedDatabases ) ; List < String > databases = new ArrayList < String > ( ) ; databases . addAll ( sortedDatabases ) ; return databases ; }


Input: { [CODESPLIT] @ Override public Set < String > databaseSet ( ) { Set < String > databases = new HashSet < String > ( ) ; addDatabases ( databases ) ; return databases ; }


Input: { [CODESPLIT] @ Override public Set < String > internalDatabaseSet ( ) { Set < String > databases = new HashSet < String > ( ) ; addInternalDatabases ( databases ) ; return databases ; }


Input: { [CODESPLIT] @ Override public Set < String > externalDatabaseSet ( ) { Set < String > databases = new HashSet < String > ( ) ; addExternalDatabases ( databases ) ; return databases ; }


Input: { [CODESPLIT] @ Override public boolean exists ( String database ) { boolean exists = internalDatabaseSet ( ) . contains ( database ) ; if ( ! exists ) { GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; GeoPackageMetadata metadata = dataSource . get ( database ) ; if ( metadata != null ) { if ( metadata . getExternalPath ( ) != null && ! new File ( metadata . getExternalPath ( ) ) . exists ( ) ) { delete ( database ) ; } else { exists = true ; } } } finally { metadataDb . close ( ) ; } } return exists ; }


Input: { [CODESPLIT] @ Override public long size ( String database ) { File dbFile = getFile ( database ) ; long size = dbFile . length ( ) ; return size ; }


Input: { [CODESPLIT] @ Override public boolean isExternal ( String database ) { boolean external = false ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; external = dataSource . isExternal ( database ) ; } finally { metadataDb . close ( ) ; } return external ; }


Input: { [CODESPLIT] @ Override public boolean existsAtExternalPath ( String path ) { GeoPackageMetadata metadata = getGeoPackageMetadataAtExternalPath ( path ) ; return metadata != null ; }


Input: { [CODESPLIT] @ Override public String getPath ( String database ) { File dbFile = getFile ( database ) ; String path = dbFile . getAbsolutePath ( ) ; return path ; }


Input: { [CODESPLIT] @ Override public File getFile ( String database ) { File dbFile = null ; GeoPackageMetadata metadata = getGeoPackageMetadata ( database ) ; if ( metadata != null && metadata . isExternal ( ) ) { dbFile = new File ( metadata . getExternalPath ( ) ) ; } else { dbFile = context . getDatabasePath ( database ) ; } if ( dbFile == null || ! dbFile . exists ( ) ) { throw new GeoPackageException ( "GeoPackage does not exist: " + database ) ; } return dbFile ; }


Input: { [CODESPLIT] @ Override public String getDatabaseAtExternalPath ( String path ) { String database = null ; GeoPackageMetadata metadata = getGeoPackageMetadataAtExternalPath ( path ) ; if ( metadata != null ) { database = metadata . getName ( ) ; } return database ; }


Input: { [CODESPLIT] @ Override public String readableSize ( String database ) { long size = size ( database ) ; return GeoPackageIOUtils . formatBytes ( size ) ; }


Input: { [CODESPLIT] @ Override public boolean delete ( String database ) { boolean deleted = false ; boolean external = isExternal ( database ) ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; deleted = dataSource . delete ( database ) ; } finally { metadataDb . close ( ) ; } if ( ! external ) { deleted = context . deleteDatabase ( database ) ; } return deleted ; }


Input: { [CODESPLIT] @ Override public boolean deleteAll ( ) { boolean deleted = true ; for ( String database : databaseSet ( ) ) { deleted = delete ( database ) && deleted ; } return deleted ; }


Input: { [CODESPLIT] @ Override public boolean deleteAllExternal ( ) { boolean deleted = true ; for ( String database : externalDatabaseSet ( ) ) { deleted = delete ( database ) && deleted ; } return deleted ; }


Input: { [CODESPLIT] @ Override public boolean deleteAllMissingExternal ( ) { boolean deleted = false ; List < GeoPackageMetadata > externalGeoPackages = getExternalGeoPackages ( ) ; for ( GeoPackageMetadata external : externalGeoPackages ) { if ( ! new File ( external . getExternalPath ( ) ) . exists ( ) ) { deleted = delete ( external . getName ( ) ) || deleted ; } } return deleted ; }


Input: { [CODESPLIT] @ Override public boolean create ( String database ) { boolean created = false ; if ( exists ( database ) ) { throw new GeoPackageException ( "GeoPackage already exists: " + database ) ; } else { GeoPackageDatabase db = new GeoPackageDatabase ( context . openOrCreateDatabase ( database , Context . MODE_PRIVATE , null ) ) ; createAndCloseGeoPackage ( db ) ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; // Save in metadata GeoPackageMetadata metadata = new GeoPackageMetadata ( ) ; metadata . setName ( database ) ; dataSource . create ( metadata ) ; } finally { metadataDb . close ( ) ; } created = true ; } return created ; }


Input: Create the required GeoPackage application id and tables in the newly created and open database connection . Then close the connection . [CODESPLIT] private void createAndCloseGeoPackage ( GeoPackageDatabase db ) { GeoPackageConnection connection = new GeoPackageConnection ( db ) ; // Set the GeoPackage application id and user version connection . setApplicationId ( ) ; connection . setUserVersion ( ) ; // Create the minimum required tables GeoPackageTableCreator tableCreator = new GeoPackageTableCreator ( connection ) ; tableCreator . createRequired ( ) ; connection . close ( ) ; }


Input: { [CODESPLIT] @ Override public boolean createAtPath ( String database , File path ) { // Create the absolute file path File file = new File ( path , database + "." + GeoPackageConstants . GEOPACKAGE_EXTENSION ) ; // Create the GeoPackage boolean created = createFile ( database , file ) ; return created ; }


Input: { [CODESPLIT] @ Override public boolean createFile ( File file ) { // Get the database name String database = GeoPackageIOUtils . getFileNameWithoutExtension ( file ) ; // Create the GeoPackage boolean created = createFile ( database , file ) ; return created ; }


Input: { [CODESPLIT] @ Override public boolean createFile ( String database , File file ) { boolean created = false ; if ( exists ( database ) ) { throw new GeoPackageException ( "GeoPackage already exists: " + database ) ; } else { // Check if the path is an absolute path to the GeoPackage file to create if ( ! GeoPackageValidate . hasGeoPackageExtension ( file ) ) { // Make sure this isn't a path to another file extension if ( GeoPackageIOUtils . getFileExtension ( file ) != null ) { throw new GeoPackageException ( "File can not have a non GeoPackage extension. Invalid File: " + file . getAbsolutePath ( ) ) ; } // Add the extension file = new File ( file . getParentFile ( ) , file . getName ( ) + "." + GeoPackageConstants . GEOPACKAGE_EXTENSION ) ; } // Make sure the file does not already exist if ( file . exists ( ) ) { throw new GeoPackageException ( "GeoPackage file already exists: " + file . getAbsolutePath ( ) ) ; } // Create the new GeoPackage file GeoPackageDatabase db = new GeoPackageDatabase ( SQLiteDatabase . openOrCreateDatabase ( file , null ) ) ; createAndCloseGeoPackage ( db ) ; // Import the GeoPackage created = importGeoPackageAsExternalLink ( file , database ) ; } return created ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String database , InputStream stream ) { return importGeoPackage ( database , stream , false , null ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String database , InputStream stream , GeoPackageProgress progress ) { return importGeoPackage ( database , stream , false , progress ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String database , InputStream stream , boolean override ) { return importGeoPackage ( database , stream , override , null ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String database , InputStream stream , boolean override , GeoPackageProgress progress ) { if ( progress != null ) { try { int streamLength = stream . available ( ) ; if ( streamLength > 0 ) { progress . setMax ( streamLength ) ; } } catch ( IOException e ) { Log . w ( GeoPackageManagerImpl . class . getSimpleName ( ) , "Could not determine stream available size. Database: " + database , e ) ; } } boolean success = importGeoPackage ( database , override , stream , progress ) ; return success ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String name , File file ) { return importGeoPackage ( name , file , false ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String name , File file , boolean override ) { // Verify the file has the right extension GeoPackageValidate . validateGeoPackageExtension ( file ) ; // Use the provided name or the base file name as the database name String database ; if ( name != null ) { database = name ; } else { database = GeoPackageIOUtils . getFileNameWithoutExtension ( file ) ; } boolean success = false ; try { FileInputStream geoPackageStream = new FileInputStream ( file ) ; success = importGeoPackage ( database , override , geoPackageStream , null ) ; } catch ( FileNotFoundException e ) { throw new GeoPackageException ( "Failed read or write GeoPackage file '" + file + "' to database: '" + database + "'" , e ) ; } return success ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String name , URL url ) { return importGeoPackage ( name , url , false , null ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String name , URL url , GeoPackageProgress progress ) { return importGeoPackage ( name , url , false , progress ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String name , URL url , boolean override ) { return importGeoPackage ( name , url , override , null ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackage ( String name , URL url , boolean override , GeoPackageProgress progress ) { boolean success = false ; HttpURLConnection connection = null ; try { connection = ( HttpURLConnection ) url . openConnection ( ) ; connection . connect ( ) ; int responseCode = connection . getResponseCode ( ) ; if ( responseCode == HttpURLConnection . HTTP_MOVED_PERM || responseCode == HttpURLConnection . HTTP_MOVED_TEMP || responseCode == HttpURLConnection . HTTP_SEE_OTHER ) { String redirect = connection . getHeaderField ( "Location" ) ; connection . disconnect ( ) ; url = new URL ( redirect ) ; connection = ( HttpURLConnection ) url . openConnection ( ) ; connection . connect ( ) ; } if ( connection . getResponseCode ( ) != HttpURLConnection . HTTP_OK ) { throw new GeoPackageException ( "Failed to import GeoPackage " + name + " from URL: '" + url . toString ( ) + "'. HTTP " + connection . getResponseCode ( ) + " " + connection . getResponseMessage ( ) ) ; } int fileLength = connection . getContentLength ( ) ; if ( fileLength != - 1 && progress != null ) { progress . setMax ( fileLength ) ; } InputStream geoPackageStream = connection . getInputStream ( ) ; success = importGeoPackage ( name , override , geoPackageStream , progress ) ; } catch ( IOException e ) { throw new GeoPackageException ( "Failed to import GeoPackage " + name + " from URL: '" + url . toString ( ) + "'" , e ) ; } finally { if ( connection != null ) { connection . disconnect ( ) ; } } return success ; }


Input: { [CODESPLIT] @ Override public void exportGeoPackage ( String database , File directory ) { exportGeoPackage ( database , database , directory ) ; }


Input: { [CODESPLIT] @ Override public void exportGeoPackage ( String database , String name , File directory ) { File file = new File ( directory , name ) ; // Add the extension if not on the name if ( ! GeoPackageValidate . hasGeoPackageExtension ( file ) ) { name += "." + GeoPackageConstants . GEOPACKAGE_EXTENSION ; file = new File ( directory , name ) ; } // Copy the geopackage database to the new file location File dbFile = getFile ( database ) ; try { GeoPackageIOUtils . copyFile ( dbFile , file ) ; } catch ( IOException e ) { throw new GeoPackageException ( "Failed read or write GeoPackage database '" + database + "' to file: '" + file , e ) ; } }


Input: { [CODESPLIT] @ Override public GeoPackage open ( String database , boolean writable ) { GeoPackage db = null ; if ( exists ( database ) ) { GeoPackageCursorFactory cursorFactory = new GeoPackageCursorFactory ( ) ; String path = null ; SQLiteDatabase sqlite = null ; GeoPackageMetadata metadata = getGeoPackageMetadata ( database ) ; if ( metadata != null && metadata . isExternal ( ) ) { path = metadata . getExternalPath ( ) ; if ( writable ) { try { sqlite = SQLiteDatabase . openDatabase ( path , cursorFactory , SQLiteDatabase . OPEN_READWRITE | SQLiteDatabase . NO_LOCALIZED_COLLATORS ) ; } catch ( Exception e ) { Log . e ( GeoPackageManagerImpl . class . getSimpleName ( ) , "Failed to open database as writable: " + database , e ) ; } } if ( sqlite == null ) { sqlite = SQLiteDatabase . openDatabase ( path , cursorFactory , SQLiteDatabase . OPEN_READONLY | SQLiteDatabase . NO_LOCALIZED_COLLATORS ) ; writable = false ; } } else { sqlite = context . openOrCreateDatabase ( database , Context . MODE_PRIVATE , cursorFactory ) ; } if ( sqliteWriteAheadLogging ) { sqlite . enableWriteAheadLogging ( ) ; } else { sqlite . disableWriteAheadLogging ( ) ; } // Validate the database if validation is enabled validateDatabaseAndCloseOnError ( sqlite , openHeaderValidation , openIntegrityValidation ) ; GeoPackageConnection connection = new GeoPackageConnection ( new GeoPackageDatabase ( sqlite ) ) ; GeoPackageTableCreator tableCreator = new GeoPackageTableCreator ( connection ) ; db = new GeoPackageImpl ( context , database , path , connection , cursorFactory , tableCreator , writable ) ; // Validate the GeoPackage has the minimum required tables try { GeoPackageValidate . validateMinimumTables ( db ) ; } catch ( RuntimeException e ) { db . close ( ) ; throw e ; } } return db ; }


Input: { [CODESPLIT] @ Override public boolean validate ( String database ) { boolean valid = isValid ( database , true , true ) ; return valid ; }


Input: { [CODESPLIT] @ Override public boolean validateHeader ( String database ) { boolean valid = isValid ( database , true , false ) ; return valid ; }


Input: { [CODESPLIT] @ Override public boolean validateIntegrity ( String database ) { boolean valid = isValid ( database , false , true ) ; return valid ; }


Input: Validate the GeoPackage database [CODESPLIT] private boolean isValid ( String database , boolean validateHeader , boolean validateIntegrity ) { boolean valid = false ; if ( exists ( database ) ) { GeoPackageCursorFactory cursorFactory = new GeoPackageCursorFactory ( ) ; String path = null ; SQLiteDatabase sqlite ; GeoPackageMetadata metadata = getGeoPackageMetadata ( database ) ; if ( metadata != null && metadata . isExternal ( ) ) { path = metadata . getExternalPath ( ) ; try { sqlite = SQLiteDatabase . openDatabase ( path , cursorFactory , SQLiteDatabase . OPEN_READWRITE | SQLiteDatabase . NO_LOCALIZED_COLLATORS ) ; } catch ( Exception e ) { sqlite = SQLiteDatabase . openDatabase ( path , cursorFactory , SQLiteDatabase . OPEN_READONLY | SQLiteDatabase . NO_LOCALIZED_COLLATORS ) ; } } else { path = context . getDatabasePath ( database ) . getAbsolutePath ( ) ; sqlite = context . openOrCreateDatabase ( database , Context . MODE_PRIVATE , cursorFactory ) ; } try { valid = ( ! validateHeader || isDatabaseHeaderValid ( sqlite ) ) && ( ! validateIntegrity || sqlite . isDatabaseIntegrityOk ( ) ) ; } catch ( Exception e ) { Log . e ( GeoPackageManagerImpl . class . getSimpleName ( ) , "Failed to validate database" , e ) ; } finally { sqlite . close ( ) ; } } return valid ; }


Input: { [CODESPLIT] @ Override public boolean copy ( String database , String databaseCopy ) { // Copy the database as a new file File dbFile = getFile ( database ) ; File dbCopyFile = context . getDatabasePath ( databaseCopy ) ; try { GeoPackageIOUtils . copyFile ( dbFile , dbCopyFile ) ; } catch ( IOException e ) { throw new GeoPackageException ( "Failed to copy GeoPackage database '" + database + "' to '" + databaseCopy + "'" , e ) ; } return exists ( databaseCopy ) ; }


Input: { [CODESPLIT] @ Override public boolean rename ( String database , String newDatabase ) { GeoPackageMetadata metadata = getGeoPackageMetadata ( database ) ; if ( metadata != null ) { GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; dataSource . rename ( metadata , newDatabase ) ; } finally { metadataDb . close ( ) ; } } if ( ( metadata == null || ! metadata . isExternal ( ) ) && copy ( database , newDatabase ) ) { delete ( database ) ; } return exists ( newDatabase ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackageAsExternalLink ( File path , String database ) { return importGeoPackageAsExternalLink ( path , database , false ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackageAsExternalLink ( File path , String database , boolean override ) { return importGeoPackageAsExternalLink ( path . getAbsolutePath ( ) , database , override ) ; }


Input: { [CODESPLIT] @ Override public boolean importGeoPackageAsExternalLink ( String path , String database , boolean override ) { if ( exists ( database ) ) { if ( override ) { if ( ! delete ( database ) ) { throw new GeoPackageException ( "Failed to delete existing database: " + database ) ; } } else { throw new GeoPackageException ( "GeoPackage database already exists: " + database ) ; } } // Verify the file is a database and can be opened try { SQLiteDatabase sqlite = SQLiteDatabase . openDatabase ( path , null , SQLiteDatabase . OPEN_READONLY | SQLiteDatabase . NO_LOCALIZED_COLLATORS ) ; validateDatabaseAndClose ( sqlite , importHeaderValidation , importIntegrityValidation ) ; } catch ( SQLiteException e ) { throw new GeoPackageException ( "Failed to import GeoPackage database as external link: " + database + ", Path: " + path , e ) ; } GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; // Save the external link in metadata GeoPackageMetadata metadata = new GeoPackageMetadata ( ) ; metadata . setName ( database ) ; metadata . setExternalPath ( path ) ; dataSource . create ( metadata ) ; GeoPackage geoPackage = open ( database , false ) ; if ( geoPackage != null ) { try { GeoPackageValidate . validateMinimumTables ( geoPackage ) ; } catch ( RuntimeException e ) { dataSource . delete ( database ) ; throw e ; } finally { geoPackage . close ( ) ; } } else { dataSource . delete ( database ) ; throw new GeoPackageException ( "Unable to open GeoPackage database. Database: " + database ) ; } } finally { metadataDb . close ( ) ; } return exists ( database ) ; }


Input: Validate the database and close when validation fails . Throw an error when not valid . [CODESPLIT] private void validateDatabaseAndCloseOnError ( SQLiteDatabase sqliteDatabase , boolean validateHeader , boolean validateIntegrity ) { validateDatabase ( sqliteDatabase , validateHeader , validateIntegrity , false , true ) ; }


Input: Validate the database and close it . Throw an error when not valid . [CODESPLIT] private void validateDatabaseAndClose ( SQLiteDatabase sqliteDatabase , boolean validateHeader , boolean validateIntegrity ) { validateDatabase ( sqliteDatabase , validateHeader , validateIntegrity , true , true ) ; }


Input: Validate the database header and integrity . Throw an error when not valid . [CODESPLIT] private void validateDatabase ( SQLiteDatabase sqliteDatabase , boolean validateHeader , boolean validateIntegrity , boolean close , boolean closeOnError ) { try { if ( validateHeader ) { validateDatabaseHeader ( sqliteDatabase ) ; } if ( validateIntegrity ) { validateDatabaseIntegrity ( sqliteDatabase ) ; } } catch ( Exception e ) { if ( closeOnError ) { sqliteDatabase . close ( ) ; } throw e ; } if ( close ) { sqliteDatabase . close ( ) ; } }


Input: Validate the header of the database file to verify it is a sqlite database [CODESPLIT] private void validateDatabaseHeader ( SQLiteDatabase sqliteDatabase ) { boolean validHeader = isDatabaseHeaderValid ( sqliteDatabase ) ; if ( ! validHeader ) { throw new GeoPackageException ( "GeoPackage SQLite header is not valid: " + sqliteDatabase . getPath ( ) ) ; } }


Input: Determine if the header of the database file is valid [CODESPLIT] private boolean isDatabaseHeaderValid ( SQLiteDatabase sqliteDatabase ) { boolean validHeader = false ; FileInputStream fis = null ; try { fis = new FileInputStream ( sqliteDatabase . getPath ( ) ) ; byte [ ] headerBytes = new byte [ 16 ] ; if ( fis . read ( headerBytes ) == 16 ) { ByteReader byteReader = new ByteReader ( headerBytes ) ; String header = byteReader . readString ( headerBytes . length ) ; String headerPrefix = header . substring ( 0 , GeoPackageConstants . SQLITE_HEADER_PREFIX . length ( ) ) ; validHeader = headerPrefix . equalsIgnoreCase ( GeoPackageConstants . SQLITE_HEADER_PREFIX ) ; } } catch ( Exception e ) { Log . e ( GeoPackageManagerImpl . class . getSimpleName ( ) , "Failed to retrieve database header" , e ) ; } finally { if ( fis != null ) { try { fis . close ( ) ; } catch ( IOException e ) { // eat } } } return validHeader ; }


Input: Add all internal databases to the collection [CODESPLIT] private void addInternalDatabases ( Collection < String > databases ) { String [ ] databaseArray = context . databaseList ( ) ; for ( String database : databaseArray ) { if ( ! isTemporary ( database ) && ! database . equalsIgnoreCase ( GeoPackageMetadataDb . DATABASE_NAME ) ) { databases . add ( database ) ; } } }


Input: Add all external databases to the collection [CODESPLIT] private void addExternalDatabases ( Collection < String > databases ) { // Get the external GeoPackages, adding those where the file exists and // deleting those with missing files List < GeoPackageMetadata > externalGeoPackages = getExternalGeoPackages ( ) ; for ( GeoPackageMetadata external : externalGeoPackages ) { if ( new File ( external . getExternalPath ( ) ) . exists ( ) ) { databases . add ( external . getName ( ) ) ; } else { delete ( external . getName ( ) ) ; } } }


Input: Import the GeoPackage stream [CODESPLIT] private boolean importGeoPackage ( String database , boolean override , InputStream geoPackageStream , GeoPackageProgress progress ) { try { if ( exists ( database ) ) { if ( override ) { if ( ! delete ( database ) ) { throw new GeoPackageException ( "Failed to delete existing database: " + database ) ; } } else { throw new GeoPackageException ( "GeoPackage database already exists: " + database ) ; } } // Copy the geopackage over as a database File newDbFile = context . getDatabasePath ( database ) ; try { SQLiteDatabase db = context . openOrCreateDatabase ( database , Context . MODE_PRIVATE , null ) ; db . close ( ) ; GeoPackageIOUtils . copyStream ( geoPackageStream , newDbFile , progress ) ; } catch ( IOException e ) { throw new GeoPackageException ( "Failed to import GeoPackage database: " + database , e ) ; } } finally { GeoPackageIOUtils . closeQuietly ( geoPackageStream ) ; } if ( progress == null || progress . isActive ( ) ) { // Verify that the database is valid try { SQLiteDatabase sqlite = context . openOrCreateDatabase ( database , Context . MODE_PRIVATE , null , new DatabaseErrorHandler ( ) { @ Override public void onCorruption ( SQLiteDatabase dbObj ) { } } ) ; validateDatabaseAndClose ( sqlite , importHeaderValidation , importIntegrityValidation ) ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; // Save in metadata GeoPackageMetadata metadata = new GeoPackageMetadata ( ) ; metadata . setName ( database ) ; dataSource . create ( metadata ) ; } finally { metadataDb . close ( ) ; } } catch ( Exception e ) { delete ( database ) ; throw new GeoPackageException ( "Invalid GeoPackage database file" , e ) ; } GeoPackage geoPackage = open ( database , false ) ; if ( geoPackage != null ) { try { if ( ! geoPackage . getSpatialReferenceSystemDao ( ) . isTableExists ( ) || ! geoPackage . getContentsDao ( ) . isTableExists ( ) ) { delete ( database ) ; throw new GeoPackageException ( "Invalid GeoPackage database file. Does not contain required tables: " + SpatialReferenceSystem . TABLE_NAME + " & " + Contents . TABLE_NAME + ", Database: " + database ) ; } } catch ( SQLException e ) { delete ( database ) ; throw new GeoPackageException ( "Invalid GeoPackage database file. Could not verify existence of required tables: " + SpatialReferenceSystem . TABLE_NAME + " & " + Contents . TABLE_NAME + ", Database: " + database ) ; } finally { geoPackage . close ( ) ; } } else { delete ( database ) ; throw new GeoPackageException ( "Unable to open GeoPackage database. Database: " + database ) ; } } return exists ( database ) ; }


Input: Get all external GeoPackage metadata [CODESPLIT] private List < GeoPackageMetadata > getExternalGeoPackages ( ) { List < GeoPackageMetadata > metadata = null ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; metadata = dataSource . getAllExternal ( ) ; } finally { metadataDb . close ( ) ; } return metadata ; }


Input: Get the GeoPackage metadata [CODESPLIT] private GeoPackageMetadata getGeoPackageMetadata ( String database ) { GeoPackageMetadata metadata = null ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; metadata = dataSource . get ( database ) ; } finally { metadataDb . close ( ) ; } return metadata ; }


Input: Get the GeoPackage metadata of the database at the external path [CODESPLIT] private GeoPackageMetadata getGeoPackageMetadataAtExternalPath ( String path ) { GeoPackageMetadata metadata = null ; GeoPackageMetadataDb metadataDb = new GeoPackageMetadataDb ( context ) ; metadataDb . open ( ) ; try { GeoPackageMetadataDataSource dataSource = new GeoPackageMetadataDataSource ( metadataDb ) ; metadata = dataSource . getExternalAtPath ( path ) ; } finally { metadataDb . close ( ) ; } return metadata ; }


Input: Check if the database is temporary ( rollback journal ) [CODESPLIT] private boolean isTemporary ( String database ) { return database . endsWith ( context . getString ( R . string . geopackage_db_rollback_journal_suffix ) ) || database . endsWith ( context . getString ( R . string . geopackage_db_write_ahead_log_suffix ) ) || database . endsWith ( context . getString ( R . string . geopackage_db_shared_memory_suffix ) ) ; }


Input: Create a new geometry metadata [CODESPLIT] public long create ( GeometryMetadata metadata ) { ContentValues values = new ContentValues ( ) ; values . put ( GeometryMetadata . COLUMN_GEOPACKAGE_ID , metadata . getGeoPackageId ( ) ) ; values . put ( GeometryMetadata . COLUMN_TABLE_NAME , metadata . getTableName ( ) ) ; values . put ( GeometryMetadata . COLUMN_ID , metadata . getId ( ) ) ; values . put ( GeometryMetadata . COLUMN_MIN_X , metadata . getMinX ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_X , metadata . getMaxX ( ) ) ; values . put ( GeometryMetadata . COLUMN_MIN_Y , metadata . getMinY ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_Y , metadata . getMaxY ( ) ) ; values . put ( GeometryMetadata . COLUMN_MIN_Z , metadata . getMinZ ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_Z , metadata . getMaxZ ( ) ) ; values . put ( GeometryMetadata . COLUMN_MIN_M , metadata . getMinM ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_M , metadata . getMaxM ( ) ) ; long insertId = db . insert ( GeometryMetadata . TABLE_NAME , null , values ) ; if ( insertId == - 1 ) { throw new GeoPackageException ( "Failed to insert geometry metadata. GeoPackage Id: " + metadata . getGeoPackageId ( ) + ", Table Name: " + metadata . getTableName ( ) + ", Geometry Id: " + metadata . getId ( ) ) ; } metadata . setId ( insertId ) ; return insertId ; }


Input: Create a new geometry metadata from an envelope [CODESPLIT] public GeometryMetadata create ( String geoPackage , String tableName , long geomId , GeometryEnvelope envelope ) { return create ( getGeoPackageId ( geoPackage ) , tableName , geomId , envelope ) ; }


Input: Create a new geometry metadata from an envelope [CODESPLIT] public GeometryMetadata create ( long geoPackageId , String tableName , long geomId , GeometryEnvelope envelope ) { GeometryMetadata metadata = populate ( geoPackageId , tableName , geomId , envelope ) ; create ( metadata ) ; return metadata ; }


Input: Populate a new geometry metadata from an envelope [CODESPLIT] public GeometryMetadata populate ( long geoPackageId , String tableName , long geomId , GeometryEnvelope envelope ) { GeometryMetadata metadata = new GeometryMetadata ( ) ; metadata . setGeoPackageId ( geoPackageId ) ; metadata . setTableName ( tableName ) ; metadata . setId ( geomId ) ; metadata . setMinX ( envelope . getMinX ( ) ) ; metadata . setMaxX ( envelope . getMaxX ( ) ) ; metadata . setMinY ( envelope . getMinY ( ) ) ; metadata . setMaxY ( envelope . getMaxY ( ) ) ; if ( envelope . hasZ ( ) ) { metadata . setMinZ ( envelope . getMinZ ( ) ) ; metadata . setMaxZ ( envelope . getMaxZ ( ) ) ; } if ( envelope . hasM ( ) ) { metadata . setMinM ( envelope . getMinM ( ) ) ; metadata . setMaxM ( envelope . getMaxM ( ) ) ; } return metadata ; }


Input: Delete the geometry metadata [CODESPLIT] public boolean delete ( GeometryMetadata metadata ) { return delete ( metadata . getGeoPackageId ( ) , metadata . getTableName ( ) , metadata . getId ( ) ) ; }


Input: Delete geometry metadata by database [CODESPLIT] public int delete ( long geoPackageId ) { String whereClause = GeometryMetadata . COLUMN_GEOPACKAGE_ID + " = ?" ; String [ ] whereArgs = new String [ ] { String . valueOf ( geoPackageId ) } ; int deleteCount = db . delete ( GeometryMetadata . TABLE_NAME , whereClause , whereArgs ) ; return deleteCount ; }


Input: Delete the geometry metadata [CODESPLIT] public boolean delete ( String geoPackage , String tableName , long id ) { return delete ( getGeoPackageId ( geoPackage ) , tableName , id ) ; }


Input: Create the geometry metadata or update if it already exists [CODESPLIT] public boolean createOrUpdate ( GeometryMetadata metadata ) { boolean success = false ; if ( exists ( metadata ) ) { success = update ( metadata ) ; } else { create ( metadata ) ; success = true ; } return success ; }


Input: Update the geometry metadata [CODESPLIT] public boolean update ( GeometryMetadata metadata ) { String whereClause = GeometryMetadata . COLUMN_GEOPACKAGE_ID + " = ? AND " + GeometryMetadata . COLUMN_TABLE_NAME + " = ? AND " + GeometryMetadata . COLUMN_ID + " = ?" ; String [ ] whereArgs = new String [ ] { String . valueOf ( metadata . getGeoPackageId ( ) ) , metadata . getTableName ( ) , String . valueOf ( metadata . getId ( ) ) } ; ContentValues values = new ContentValues ( ) ; values . put ( GeometryMetadata . COLUMN_MIN_X , metadata . getMinX ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_X , metadata . getMaxX ( ) ) ; values . put ( GeometryMetadata . COLUMN_MIN_Y , metadata . getMinY ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_Y , metadata . getMaxY ( ) ) ; values . put ( GeometryMetadata . COLUMN_MIN_Z , metadata . getMinZ ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_Z , metadata . getMaxZ ( ) ) ; values . put ( GeometryMetadata . COLUMN_MIN_M , metadata . getMinM ( ) ) ; values . put ( GeometryMetadata . COLUMN_MAX_M , metadata . getMaxM ( ) ) ; int updateCount = db . update ( GeometryMetadata . TABLE_NAME , values , whereClause , whereArgs ) ; return updateCount > 0 ; }


Input: Get a table metadata [CODESPLIT] public GeometryMetadata get ( GeometryMetadata metadata ) { return get ( metadata . getGeoPackageId ( ) , metadata . getTableName ( ) , metadata . getId ( ) ) ; }


Input: Get a table metadata [CODESPLIT] public GeometryMetadata get ( String geoPackage , String tableName , long id ) { return get ( getGeoPackageId ( geoPackage ) , tableName , id ) ; }


Input: Get a table metadata [CODESPLIT] public GeometryMetadata get ( long geoPackageId , String tableName , long id ) { String selection = GeometryMetadata . COLUMN_GEOPACKAGE_ID + " = ? AND " + GeometryMetadata . COLUMN_TABLE_NAME + " = ? AND " + GeometryMetadata . COLUMN_ID + " = ?" ; String [ ] selectionArgs = new String [ ] { String . valueOf ( geoPackageId ) , tableName , String . valueOf ( id ) } ; Cursor cursor = db . query ( GeometryMetadata . TABLE_NAME , GeometryMetadata . COLUMNS , selection , selectionArgs , null , null , null ) ; GeometryMetadata metadata = null ; try { if ( cursor . moveToNext ( ) ) { metadata = createGeometryMetadata ( cursor ) ; } } finally { cursor . close ( ) ; } return metadata ; }


Input: Query for all table geometry metadata [CODESPLIT] public Cursor query ( String geoPackage , String tableName ) { return query ( getGeoPackageId ( geoPackage ) , tableName ) ; }


Input: Query for the bounds of the feature table index [CODESPLIT] public BoundingBox getBoundingBox ( String geoPackage , String tableName ) { return getBoundingBox ( getGeoPackageId ( geoPackage ) , tableName ) ; }


Input: Query for the bounds of the feature table index [CODESPLIT] public BoundingBox getBoundingBox ( long geoPackageId , String tableName ) { BoundingBox boundingBox = null ; Cursor result = db . rawQuery ( "SELECT MIN(" + GeometryMetadata . COLUMN_MIN_X + "), MIN(" + GeometryMetadata . COLUMN_MIN_Y + "), MAX(" + GeometryMetadata . COLUMN_MAX_X + "), MAX(" + GeometryMetadata . COLUMN_MAX_Y + ") FROM " + GeometryMetadata . TABLE_NAME + " WHERE " + GeometryMetadata . COLUMN_GEOPACKAGE_ID + " = ? AND " + GeometryMetadata . COLUMN_TABLE_NAME + " = ?" , new String [ ] { String . valueOf ( geoPackageId ) , tableName } ) ; try { if ( result . moveToNext ( ) ) { boundingBox = new BoundingBox ( result . getDouble ( 0 ) , result . getDouble ( 1 ) , result . getDouble ( 2 ) , result . getDouble ( 3 ) ) ; } } finally { result . close ( ) ; } return boundingBox ; }


Input: Query for all table geometry metadata [CODESPLIT] public Cursor query ( long geoPackageId , String tableName ) { String selection = GeometryMetadata . COLUMN_GEOPACKAGE_ID + " = ? AND " + GeometryMetadata . COLUMN_TABLE_NAME + " = ?" ; String [ ] selectionArgs = new String [ ] { String . valueOf ( geoPackageId ) , tableName } ; Cursor cursor = db . query ( GeometryMetadata . TABLE_NAME , GeometryMetadata . COLUMNS , selection , selectionArgs , null , null , null ) ; return cursor ; }


Input: Query for all table geometry metadata matching the bounding box in the same projection [CODESPLIT] public Cursor query ( String geoPackage , String tableName , BoundingBox boundingBox ) { return query ( getGeoPackageId ( geoPackage ) , tableName , boundingBox ) ; }


Input: Query for all table geometry metadata count matching the bounding box in the same projection [CODESPLIT] public int count ( String geoPackage , String tableName , BoundingBox boundingBox ) { return count ( getGeoPackageId ( geoPackage ) , tableName , boundingBox ) ; }


Input: Query for all table geometry metadata matching the bounding box in the same projection [CODESPLIT] public Cursor query ( long geoPackageId , String tableName , BoundingBox boundingBox ) { GeometryEnvelope envelope = new GeometryEnvelope ( ) ; envelope . setMinX ( boundingBox . getMinLongitude ( ) ) ; envelope . setMaxX ( boundingBox . getMaxLongitude ( ) ) ; envelope . setMinY ( boundingBox . getMinLatitude ( ) ) ; envelope . setMaxY ( boundingBox . getMaxLatitude ( ) ) ; return query ( geoPackageId , tableName , envelope ) ; }


Input: Query for all table geometry metadata matching the envelope [CODESPLIT] public Cursor query ( String geoPackage , String tableName , GeometryEnvelope envelope ) { return query ( getGeoPackageId ( geoPackage ) , tableName , envelope ) ; }


Input: Query for all table geometry metadata count matching the envelope [CODESPLIT] public int count ( String geoPackage , String tableName , GeometryEnvelope envelope ) { return count ( getGeoPackageId ( geoPackage ) , tableName , envelope ) ; }


Input: Query for all table geometry metadata matching the envelope [CODESPLIT] public Cursor query ( long geoPackageId , String tableName , GeometryEnvelope envelope ) { StringBuilder selection = new StringBuilder ( ) ; selection . append ( GeometryMetadata . COLUMN_GEOPACKAGE_ID ) . append ( " = ? AND " ) . append ( GeometryMetadata . COLUMN_TABLE_NAME ) . append ( " = ?" ) ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MIN_X ) . append ( " <= ?" ) ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MAX_X ) . append ( " >= ?" ) ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MIN_Y ) . append ( " <= ?" ) ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MAX_Y ) . append ( " >= ?" ) ; int args = 6 ; if ( envelope . hasZ ( ) ) { args += 2 ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MIN_Z ) . append ( " <= ?" ) ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MAX_Z ) . append ( " >= ?" ) ; } if ( envelope . hasM ( ) ) { args += 2 ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MIN_M ) . append ( " <= ?" ) ; selection . append ( " AND " ) . append ( GeometryMetadata . COLUMN_MAX_M ) . append ( " >= ?" ) ; } double minX = envelope . getMinX ( ) - tolerance ; double maxX = envelope . getMaxX ( ) + tolerance ; double minY = envelope . getMinY ( ) - tolerance ; double maxY = envelope . getMaxY ( ) + tolerance ; String [ ] selectionArgs = new String [ args ] ; int argCount = 0 ; selectionArgs [ argCount ++ ] = String . valueOf ( geoPackageId ) ; selectionArgs [ argCount ++ ] = tableName ; selectionArgs [ argCount ++ ] = String . valueOf ( maxX ) ; selectionArgs [ argCount ++ ] = String . valueOf ( minX ) ; selectionArgs [ argCount ++ ] = String . valueOf ( maxY ) ; selectionArgs [ argCount ++ ] = String . valueOf ( minY ) ; if ( envelope . hasZ ( ) ) { double minZ = envelope . getMinZ ( ) - tolerance ; double maxZ = envelope . getMaxZ ( ) + tolerance ; selectionArgs [ argCount ++ ] = String . valueOf ( maxZ ) ; selectionArgs [ argCount ++ ] = String . valueOf ( minZ ) ; } if ( envelope . hasM ( ) ) { double minM = envelope . getMinM ( ) - tolerance ; double maxM = envelope . getMaxM ( ) + tolerance ; selectionArgs [ argCount ++ ] = String . valueOf ( maxM ) ; selectionArgs [ argCount ++ ] = String . valueOf ( minM ) ; } Cursor cursor = db . query ( GeometryMetadata . TABLE_NAME , GeometryMetadata . COLUMNS , selection . toString ( ) , selectionArgs , null , null , null ) ; return cursor ; }


Input: Query for all table geometry metadata count matching the envelope [CODESPLIT] public int count ( long geoPackageId , String tableName , GeometryEnvelope envelope ) { Cursor cursor = query ( geoPackageId , tableName , envelope ) ; int count = cursor . getCount ( ) ; cursor . close ( ) ; return count ; }


Input: Create a geometry metadata from the current cursor location [CODESPLIT] public static GeometryMetadata createGeometryMetadata ( Cursor cursor ) { GeometryMetadata metadata = new GeometryMetadata ( ) ; metadata . setGeoPackageId ( cursor . getLong ( 0 ) ) ; metadata . setTableName ( cursor . getString ( 1 ) ) ; metadata . setId ( cursor . getLong ( 2 ) ) ; metadata . setMinX ( cursor . getDouble ( 3 ) ) ; metadata . setMaxX ( cursor . getDouble ( 4 ) ) ; metadata . setMinY ( cursor . getDouble ( 5 ) ) ; metadata . setMaxY ( cursor . getDouble ( 6 ) ) ; if ( ! cursor . isNull ( 7 ) ) { metadata . setMinZ ( cursor . getDouble ( 7 ) ) ; } if ( ! cursor . isNull ( 8 ) ) { metadata . setMaxZ ( cursor . getDouble ( 8 ) ) ; } if ( ! cursor . isNull ( 9 ) ) { metadata . setMinM ( cursor . getDouble ( 9 ) ) ; } if ( ! cursor . isNull ( 10 ) ) { metadata . setMaxM ( cursor . getDouble ( 10 ) ) ; } return metadata ; }


Input: { [CODESPLIT] @ Override public TRow queryForIdRow ( long id ) { TRow row = null ; TResult readCursor = queryForId ( id ) ; if ( readCursor . moveToNext ( ) ) { row = readCursor . getRow ( ) ; if ( ! row . isValid ( ) && readCursor . moveToNext ( ) ) { row = readCursor . getRow ( ) ; } } readCursor . close ( ) ; return row ; }


Input: Update all rows matching the where clause with the provided values [CODESPLIT] public int update ( ContentValues values , String whereClause , String [ ] whereArgs ) { return db . update ( getTableName ( ) , values , whereClause , whereArgs ) ; }


Input: { [CODESPLIT] @ Override public long insert ( TRow row ) { long id = db . insertOrThrow ( getTableName ( ) , null , row . toContentValues ( ) ) ; if ( row . hasIdColumn ( ) ) { row . setId ( id ) ; } return id ; }


Input: { [CODESPLIT] @ Override public Bitmap drawTile ( int tileWidth , int tileHeight , long tileFeatureCount , FeatureIndexResults featureIndexResults ) { String featureText = String . valueOf ( tileFeatureCount ) ; Bitmap bitmap = drawTile ( tileWidth , tileHeight , featureText ) ; return bitmap ; }


Input: { [CODESPLIT] @ Override public Bitmap drawUnindexedTile ( int tileWidth , int tileHeight , long totalFeatureCount , FeatureCursor allFeatureResults ) { Bitmap bitmap = null ; if ( drawUnindexedTiles ) { // Draw a tile indicating we have no idea if there are features inside. // The table is not indexed and more features exist than the max feature count set. bitmap = drawTile ( tileWidth , tileHeight , "?" ) ; } return bitmap ; }


Input: Draw a tile with the provided text label in the middle [CODESPLIT] private Bitmap drawTile ( int tileWidth , int tileHeight , String text ) { // Create bitmap and canvas Bitmap bitmap = Bitmap . createBitmap ( tileWidth , tileHeight , Bitmap . Config . ARGB_8888 ) ; Canvas canvas = new Canvas ( bitmap ) ; // Draw the tile fill paint if ( tileFillPaint != null ) { canvas . drawRect ( 0 , 0 , tileWidth , tileHeight , tileFillPaint ) ; } // Draw the tile border if ( tileBorderPaint != null ) { canvas . drawRect ( 0 , 0 , tileWidth , tileHeight , tileBorderPaint ) ; } // Determine the text bounds Rect textBounds = new Rect ( ) ; textPaint . getTextBounds ( text , 0 , text . length ( ) , textBounds ) ; // Determine the center of the tile int centerX = ( int ) ( bitmap . getWidth ( ) / 2.0f ) ; int centerY = ( int ) ( bitmap . getHeight ( ) / 2.0f ) ; // Draw the circle if ( circlePaint != null || circleFillPaint != null ) { int diameter = Math . max ( textBounds . width ( ) , textBounds . height ( ) ) ; float radius = diameter / 2.0f ; radius = radius + ( diameter * circlePaddingPercentage ) ; // Draw the filled circle if ( circleFillPaint != null ) { canvas . drawCircle ( centerX , centerY , radius , circleFillPaint ) ; } // Draw the circle if ( circlePaint != null ) { canvas . drawCircle ( centerX , centerY , radius , circlePaint ) ; } } // Draw the text canvas . drawText ( text , centerX - textBounds . exactCenterX ( ) , centerY - textBounds . exactCenterY ( ) , textPaint ) ; return bitmap ; }


Input: Get the simple attributes rows that exist with the provided ids [CODESPLIT] public List < SimpleAttributesRow > getRows ( List < Long > ids ) { List < SimpleAttributesRow > simpleAttributesRows = new ArrayList <> ( ) ; for ( long id : ids ) { UserCustomRow userCustomRow = queryForIdRow ( id ) ; if ( userCustomRow != null ) { simpleAttributesRows . add ( getRow ( userCustomRow ) ) ; } } return simpleAttributesRows ; }


Input: { [CODESPLIT] @ Override protected BoundingBox getFeatureBoundingBox ( Projection projection , String table , boolean manual ) { BoundingBox boundingBox = null ; FeatureIndexManager indexManager = new FeatureIndexManager ( context , this , table ) ; try { if ( manual || indexManager . isIndexed ( ) ) { boundingBox = indexManager . getBoundingBox ( projection ) ; } } finally { indexManager . close ( ) ; } return boundingBox ; }


Input: { [CODESPLIT] @ Override public void registerCursorWrapper ( String table , GeoPackageCursorWrapper cursorWrapper ) { cursorFactory . registerTable ( table , cursorWrapper ) ; }


Input: { [CODESPLIT] @ Override public FeatureDao getFeatureDao ( GeometryColumns geometryColumns ) { if ( geometryColumns == null ) { throw new GeoPackageException ( "Non null " + GeometryColumns . class . getSimpleName ( ) + " is required to create " + FeatureDao . class . getSimpleName ( ) ) ; } // Read the existing table and create the dao FeatureTableReader tableReader = new FeatureTableReader ( geometryColumns ) ; final FeatureTable featureTable = tableReader . readTable ( new FeatureWrapperConnection ( database ) ) ; featureTable . setContents ( geometryColumns . getContents ( ) ) ; FeatureConnection userDb = new FeatureConnection ( database ) ; FeatureDao dao = new FeatureDao ( getName ( ) , database , userDb , geometryColumns , featureTable ) ; // Register the table name (with and without quotes) to wrap cursors with the feature cursor registerCursorWrapper ( geometryColumns . getTableName ( ) , new GeoPackageCursorWrapper ( ) { @ Override public Cursor wrapCursor ( Cursor cursor ) { return new FeatureCursor ( featureTable , cursor ) ; } } ) ; // If the GeoPackage is writable and the feature table has a RTree Index // extension, drop the RTree triggers.  User defined functions are currently not supported. if ( writable ) { RTreeIndexExtension rtree = new RTreeIndexExtension ( this ) ; rtree . dropTriggers ( featureTable ) ; } return dao ; }


Input: { [CODESPLIT] @ Override public FeatureDao getFeatureDao ( Contents contents ) { if ( contents == null ) { throw new GeoPackageException ( "Non null " + Contents . class . getSimpleName ( ) + " is required to create " + FeatureDao . class . getSimpleName ( ) ) ; } GeometryColumns geometryColumns = contents . getGeometryColumns ( ) ; if ( geometryColumns == null ) { throw new GeoPackageException ( "No " + GeometryColumns . class . getSimpleName ( ) + " exists for " + Contents . class . getSimpleName ( ) + " " + contents . getId ( ) ) ; } return getFeatureDao ( geometryColumns ) ; }


Input: { [CODESPLIT] @ Override public FeatureDao getFeatureDao ( String tableName ) { GeometryColumnsDao dao = getGeometryColumnsDao ( ) ; List < GeometryColumns > geometryColumnsList ; try { geometryColumnsList = dao . queryForEq ( GeometryColumns . COLUMN_TABLE_NAME , tableName ) ; } catch ( SQLException e ) { throw new GeoPackageException ( "Failed to retrieve " + FeatureDao . class . getSimpleName ( ) + " for table name: " + tableName + ". Exception retrieving " + GeometryColumns . class . getSimpleName ( ) + "." , e ) ; } if ( geometryColumnsList . isEmpty ( ) ) { throw new GeoPackageException ( "No Feature Table exists for table name: " + tableName ) ; } else if ( geometryColumnsList . size ( ) > 1 ) { // This shouldn't happen with the table name unique constraint on // geometry columns throw new GeoPackageException ( "Unexpected state. More than one " + GeometryColumns . class . getSimpleName ( ) + " matched for table name: " + tableName + ", count: " + geometryColumnsList . size ( ) ) ; } return getFeatureDao ( geometryColumnsList . get ( 0 ) ) ; }


Input: { [CODESPLIT] @ Override public TileDao getTileDao ( Contents contents ) { if ( contents == null ) { throw new GeoPackageException ( "Non null " + Contents . class . getSimpleName ( ) + " is required to create " + TileDao . class . getSimpleName ( ) ) ; } TileMatrixSet tileMatrixSet = contents . getTileMatrixSet ( ) ; if ( tileMatrixSet == null ) { throw new GeoPackageException ( "No " + TileMatrixSet . class . getSimpleName ( ) + " exists for " + Contents . class . getSimpleName ( ) + " " + contents . getId ( ) ) ; } return getTileDao ( tileMatrixSet ) ; }


Input: { [CODESPLIT] @ Override public AttributesDao getAttributesDao ( Contents contents ) { if ( contents == null ) { throw new GeoPackageException ( "Non null " + Contents . class . getSimpleName ( ) + " is required to create " + AttributesDao . class . getSimpleName ( ) ) ; } if ( contents . getDataType ( ) != ContentsDataType . ATTRIBUTES ) { throw new GeoPackageException ( Contents . class . getSimpleName ( ) + " is required to be of type " + ContentsDataType . ATTRIBUTES + ". Actual: " + contents . getDataTypeString ( ) ) ; } // Read the existing table and create the dao AttributesTableReader tableReader = new AttributesTableReader ( contents . getTableName ( ) ) ; final AttributesTable attributesTable = tableReader . readTable ( new AttributesWrapperConnection ( database ) ) ; attributesTable . setContents ( contents ) ; AttributesConnection userDb = new AttributesConnection ( database ) ; AttributesDao dao = new AttributesDao ( getName ( ) , database , userDb , attributesTable ) ; // Register the table name (with and without quotes) to wrap cursors with the attributes cursor registerCursorWrapper ( attributesTable . getTableName ( ) , new GeoPackageCursorWrapper ( ) { @ Override public Cursor wrapCursor ( Cursor cursor ) { return new AttributesCursor ( attributesTable , cursor ) ; } } ) ; return dao ; }


Input: { [CODESPLIT] @ Override public AttributesDao getAttributesDao ( String tableName ) { ContentsDao dao = getContentsDao ( ) ; Contents contents = null ; try { contents = dao . queryForId ( tableName ) ; } catch ( SQLException e ) { throw new GeoPackageException ( "Failed to retrieve " + Contents . class . getSimpleName ( ) + " for table name: " + tableName , e ) ; } if ( contents == null ) { throw new GeoPackageException ( "No Contents Table exists for table name: " + tableName ) ; } return getAttributesDao ( contents ) ; }


Input: { [CODESPLIT] @ Override public Cursor rawQuery ( String sql , String [ ] args ) { return database . rawQuery ( sql , args ) ; }


Input: { [CODESPLIT] @ Override public Cursor foreignKeyCheck ( ) { Cursor cursor = rawQuery ( "PRAGMA foreign_key_check" , null ) ; if ( ! cursor . moveToNext ( ) ) { cursor . close ( ) ; cursor = null ; } return cursor ; }


Input: Check the cursor returned from the integrity check to see if things are ok [CODESPLIT] private Cursor integrityCheck ( Cursor cursor ) { if ( cursor . moveToNext ( ) ) { String value = cursor . getString ( 0 ) ; if ( value . equals ( "ok" ) ) { cursor . close ( ) ; cursor = null ; } } return cursor ; }


Input: { [CODESPLIT] @ Override public String getPrimaryKeyColumnName ( String tableName ) { UserCustomTable table = UserCustomTableReader . readTable ( connection , tableName ) ; UserCustomColumn pkColumn = table . getPkColumn ( ) ; if ( pkColumn == null ) { throw new GeoPackageException ( "Found no primary key for table " + tableName ) ; } return pkColumn . getName ( ) ; }


Input: Get a User Mapping DAO from a table name [CODESPLIT] public UserMappingDao getMappingDao ( String tableName ) { UserMappingDao userMappingDao = new UserMappingDao ( getUserDao ( tableName ) ) ; userMappingDao . registerCursorWrapper ( getGeoPackage ( ) ) ; return userMappingDao ; }


Input: Get a related simple attributes table DAO [CODESPLIT] public SimpleAttributesDao getSimpleAttributesDao ( String tableName ) { SimpleAttributesDao simpleAttributesDao = new SimpleAttributesDao ( getUserDao ( tableName ) ) ; simpleAttributesDao . registerCursorWrapper ( getGeoPackage ( ) ) ; setContents ( simpleAttributesDao . getTable ( ) ) ; return simpleAttributesDao ; }


Input: Get the related id mappings for the base id [CODESPLIT] public List < Long > getMappingsForBase ( ExtendedRelation extendedRelation , long baseId ) { return getMappingsForBase ( extendedRelation . getMappingTableName ( ) , baseId ) ; }


Input: Get the base id mappings for the related id [CODESPLIT] public List < Long > getMappingsForRelated ( ExtendedRelation extendedRelation , long relatedId ) { return getMappingsForRelated ( extendedRelation . getMappingTableName ( ) , relatedId ) ; }


Input: Determine if the base id and related id mapping exists [CODESPLIT] public boolean hasMapping ( String tableName , long baseId , long relatedId ) { boolean has = false ; UserMappingDao userMappingDao = getMappingDao ( tableName ) ; UserCustomCursor cursor = userMappingDao . queryByIds ( baseId , relatedId ) ; try { has = cursor . getCount ( ) > 0 ; } finally { cursor . close ( ) ; } return has ; }


Input: { [CODESPLIT] @ Override public TileRow getRow ( int [ ] columnTypes , Object [ ] values ) { return new TileRow ( getTable ( ) , columnTypes , values ) ; }


Input: { [CODESPLIT] @ Override protected UserInvalidCursor < TileColumn , TileTable , TileRow , ? extends UserCursor < TileColumn , TileTable , TileRow > , ? extends UserDao < TileColumn , TileTable , TileRow , ? extends UserCursor < TileColumn , TileTable , TileRow > > > createInvalidCursor ( UserDao dao , UserCursor cursor , List < Integer > invalidPositions , List < TileColumn > blobColumns ) { return new TileInvalidCursor ( ( TileDao ) dao , ( TileCursor ) cursor , invalidPositions , blobColumns ) ; }


Input: Get the count of the cursor and close it [CODESPLIT] protected int count ( UserCustomCursor cursor ) { int count = 0 ; try { count = cursor . getCount ( ) ; } finally { cursor . close ( ) ; } return count ; }


Input: Register the cursor wrapper into the GeoPackage [CODESPLIT] public void registerCursorWrapper ( GeoPackage geoPackage ) { geoPackage . registerCursorWrapper ( getTableName ( ) , new GeoPackageCursorWrapper ( ) { @ Override public Cursor wrapCursor ( Cursor cursor ) { return new UserCustomCursor ( getTable ( ) , cursor ) ; } } ) ; }


Input: Read the database table and create a DAO [CODESPLIT] public static UserCustomDao readTable ( GeoPackage geoPackage , String tableName ) { UserCustomConnection userDb = new UserCustomConnection ( geoPackage . getConnection ( ) ) ; final UserCustomTable userCustomTable = UserCustomTableReader . readTable ( geoPackage . getConnection ( ) , tableName ) ; UserCustomDao dao = new UserCustomDao ( geoPackage . getName ( ) , geoPackage . getConnection ( ) , userDb , userCustomTable ) ; dao . registerCursorWrapper ( geoPackage ) ; return dao ; }


Input: Get the tile from the request bounding box in the request projection [CODESPLIT] public GeoPackageTile getTile ( BoundingBox requestBoundingBox ) { GeoPackageTile tile = null ; // Transform to the projection of the tiles ProjectionTransform transformRequestToTiles = requestProjection . getTransformation ( tilesProjection ) ; BoundingBox tilesBoundingBox = requestBoundingBox . transform ( transformRequestToTiles ) ; List < TileMatrix > tileMatrices = getTileMatrices ( tilesBoundingBox ) ; for ( int i = 0 ; tile == null && i < tileMatrices . size ( ) ; i ++ ) { TileMatrix tileMatrix = tileMatrices . get ( i ) ; TileCursor tileResults = retrieveTileResults ( tilesBoundingBox , tileMatrix ) ; if ( tileResults != null ) { try { if ( tileResults . getCount ( ) > 0 ) { BoundingBox requestProjectedBoundingBox = requestBoundingBox . transform ( transformRequestToTiles ) ; // Determine the requested tile dimensions, or use the dimensions of a single tile matrix tile int requestedTileWidth = width != null ? width : ( int ) tileMatrix . getTileWidth ( ) ; int requestedTileHeight = height != null ? height : ( int ) tileMatrix . getTileHeight ( ) ; // Determine the size of the tile to initially draw int tileWidth = requestedTileWidth ; int tileHeight = requestedTileHeight ; if ( ! sameProjection ) { tileWidth = ( int ) Math . round ( ( requestProjectedBoundingBox . getMaxLongitude ( ) - requestProjectedBoundingBox . getMinLongitude ( ) ) / tileMatrix . getPixelXSize ( ) ) ; tileHeight = ( int ) Math . round ( ( requestProjectedBoundingBox . getMaxLatitude ( ) - requestProjectedBoundingBox . getMinLatitude ( ) ) / tileMatrix . getPixelYSize ( ) ) ; } // Draw the resulting bitmap with the matching tiles Bitmap tileBitmap = drawTile ( tileMatrix , tileResults , requestProjectedBoundingBox , tileWidth , tileHeight ) ; // Create the tile if ( tileBitmap != null ) { // Project the tile if needed if ( ! sameProjection ) { Bitmap reprojectTile = reprojectTile ( tileBitmap , requestedTileWidth , requestedTileHeight , requestBoundingBox , transformRequestToTiles , tilesBoundingBox ) ; tileBitmap . recycle ( ) ; tileBitmap = reprojectTile ; } try { byte [ ] tileData = BitmapConverter . toBytes ( tileBitmap , COMPRESS_FORMAT ) ; tileBitmap . recycle ( ) ; tile = new GeoPackageTile ( requestedTileWidth , requestedTileHeight , tileData ) ; } catch ( IOException e ) { Log . e ( TileCreator . class . getSimpleName ( ) , "Failed to create tile. min lat: " + requestBoundingBox . getMinLatitude ( ) + ", max lat: " + requestBoundingBox . getMaxLatitude ( ) + ", min lon: " + requestBoundingBox . getMinLongitude ( ) + ", max lon: " + requestBoundingBox . getMaxLongitude ( ) , e ) ; } } } } finally { tileResults . close ( ) ; } } } return tile ; }


Input: Draw the tile from the tile results [CODESPLIT] private Bitmap drawTile ( TileMatrix tileMatrix , TileCursor tileResults , BoundingBox requestProjectedBoundingBox , int tileWidth , int tileHeight ) { // Draw the resulting bitmap with the matching tiles Bitmap tileBitmap = null ; Canvas canvas = null ; Paint paint = null ; while ( tileResults . moveToNext ( ) ) { // Get the next tile TileRow tileRow = tileResults . getRow ( ) ; Bitmap tileDataBitmap = tileRow . getTileDataBitmap ( ) ; // Get the bounding box of the tile BoundingBox tileBoundingBox = TileBoundingBoxUtils . getBoundingBox ( tileSetBoundingBox , tileMatrix , tileRow . getTileColumn ( ) , tileRow . getTileRow ( ) ) ; // Get the bounding box where the requested image and // tile overlap BoundingBox overlap = requestProjectedBoundingBox . overlap ( tileBoundingBox ) ; // If the tile overlaps with the requested box if ( overlap != null ) { // Get the rectangle of the tile image to draw Rect src = TileBoundingBoxAndroidUtils . getRectangle ( tileMatrix . getTileWidth ( ) , tileMatrix . getTileHeight ( ) , tileBoundingBox , overlap ) ; // Get the rectangle of where to draw the tile in // the resulting image RectF dest = TileBoundingBoxAndroidUtils . getRoundedFloatRectangle ( tileWidth , tileHeight , requestProjectedBoundingBox , overlap ) ; // Create the bitmap first time through if ( tileBitmap == null ) { tileBitmap = Bitmap . createBitmap ( tileWidth , tileHeight , Bitmap . Config . ARGB_8888 ) ; canvas = new Canvas ( tileBitmap ) ; paint = new Paint ( Paint . ANTI_ALIAS_FLAG ) ; } // Draw the tile to the bitmap canvas . drawBitmap ( tileDataBitmap , src , dest , paint ) ; } } return tileBitmap ; }


Input: Reproject the tile to the requested projection [CODESPLIT] private Bitmap reprojectTile ( Bitmap tile , int requestedTileWidth , int requestedTileHeight , BoundingBox requestBoundingBox , ProjectionTransform transformRequestToTiles , BoundingBox tilesBoundingBox ) { final double requestedWidthUnitsPerPixel = ( requestBoundingBox . getMaxLongitude ( ) - requestBoundingBox . getMinLongitude ( ) ) / requestedTileWidth ; final double requestedHeightUnitsPerPixel = ( requestBoundingBox . getMaxLatitude ( ) - requestBoundingBox . getMinLatitude ( ) ) / requestedTileHeight ; final double tilesDistanceWidth = tilesBoundingBox . getMaxLongitude ( ) - tilesBoundingBox . getMinLongitude ( ) ; final double tilesDistanceHeight = tilesBoundingBox . getMaxLatitude ( ) - tilesBoundingBox . getMinLatitude ( ) ; final int width = tile . getWidth ( ) ; final int height = tile . getHeight ( ) ; // Tile pixels of the tile matrix tiles int [ ] pixels = new int [ width * height ] ; tile . getPixels ( pixels , 0 , width , 0 , 0 , width , height ) ; // Projected tile pixels to draw the reprojected tile int [ ] projectedPixels = new int [ requestedTileWidth * requestedTileHeight ] ; // Retrieve each pixel in the new tile from the unprojected tile for ( int y = 0 ; y < requestedTileHeight ; y ++ ) { for ( int x = 0 ; x < requestedTileWidth ; x ++ ) { double longitude = requestBoundingBox . getMinLongitude ( ) + ( x * requestedWidthUnitsPerPixel ) ; double latitude = requestBoundingBox . getMaxLatitude ( ) - ( y * requestedHeightUnitsPerPixel ) ; ProjCoordinate fromCoord = new ProjCoordinate ( longitude , latitude ) ; ProjCoordinate toCoord = transformRequestToTiles . transform ( fromCoord ) ; double projectedLongitude = toCoord . x ; double projectedLatitude = toCoord . y ; int xPixel = ( int ) Math . round ( ( ( projectedLongitude - tilesBoundingBox . getMinLongitude ( ) ) / tilesDistanceWidth ) * width ) ; int yPixel = ( int ) Math . round ( ( ( tilesBoundingBox . getMaxLatitude ( ) - projectedLatitude ) / tilesDistanceHeight ) * height ) ; xPixel = Math . max ( 0 , xPixel ) ; xPixel = Math . min ( width - 1 , xPixel ) ; yPixel = Math . max ( 0 , yPixel ) ; yPixel = Math . min ( height - 1 , yPixel ) ; int color = pixels [ ( yPixel * width ) + xPixel ] ; projectedPixels [ ( y * requestedTileWidth ) + x ] = color ; } } // Draw the new tile bitmap Bitmap projectedTileBitmap = Bitmap . createBitmap ( requestedTileWidth , requestedTileHeight , tile . getConfig ( ) ) ; projectedTileBitmap . setPixels ( projectedPixels , 0 , requestedTileWidth , 0 , 0 , requestedTileWidth , requestedTileHeight ) ; return projectedTileBitmap ; }


Input: Get the tile matrices that may contain the tiles for the bounding box matches against the bounding box and zoom level options [CODESPLIT] private List < TileMatrix > getTileMatrices ( BoundingBox projectedRequestBoundingBox ) { List < TileMatrix > tileMatrices = new ArrayList <> ( ) ; // Check if the request overlaps the tile matrix set if ( ! tileDao . getTileMatrices ( ) . isEmpty ( ) && projectedRequestBoundingBox . intersects ( tileSetBoundingBox ) ) { // Get the tile distance double distanceWidth = projectedRequestBoundingBox . getMaxLongitude ( ) - projectedRequestBoundingBox . getMinLongitude ( ) ; double distanceHeight = projectedRequestBoundingBox . getMaxLatitude ( ) - projectedRequestBoundingBox . getMinLatitude ( ) ; // Get the zoom level to request based upon the tile size Long requestZoomLevel = null ; if ( scaling != null ) { // When options are provided, get the approximate zoom level regardless of whether a tile level exists requestZoomLevel = tileDao . getApproximateZoomLevel ( distanceWidth , distanceHeight ) ; } else { // Get the closest existing zoom level requestZoomLevel = tileDao . getZoomLevel ( distanceWidth , distanceHeight ) ; } // If there is a matching zoom level if ( requestZoomLevel != null ) { List < Long > zoomLevels = null ; // If options are configured, build the possible zoom levels in order to request if ( scaling != null && scaling . getScalingType ( ) != null ) { // Find zoom in levels List < Long > zoomInLevels = new ArrayList <> ( ) ; if ( scaling . isZoomIn ( ) ) { long zoomIn = scaling . getZoomIn ( ) != null ? requestZoomLevel + scaling . getZoomIn ( ) : tileDao . getMaxZoom ( ) ; for ( long zoomLevel = requestZoomLevel + 1 ; zoomLevel <= zoomIn ; zoomLevel ++ ) { zoomInLevels . add ( zoomLevel ) ; } } // Find zoom out levels List < Long > zoomOutLevels = new ArrayList <> ( ) ; if ( scaling . isZoomOut ( ) ) { long zoomOut = scaling . getZoomOut ( ) != null ? requestZoomLevel - scaling . getZoomOut ( ) : tileDao . getMinZoom ( ) ; for ( long zoomLevel = requestZoomLevel - 1 ; zoomLevel >= zoomOut ; zoomLevel -- ) { zoomOutLevels . add ( zoomLevel ) ; } } if ( zoomInLevels . isEmpty ( ) ) { // Only zooming out zoomLevels = zoomOutLevels ; } else if ( zoomOutLevels . isEmpty ( ) ) { // Only zooming in zoomLevels = zoomInLevels ; } else { // Determine how to order the zoom in and zoom out levels TileScalingType type = scaling . getScalingType ( ) ; switch ( type ) { case IN : case IN_OUT : // Order zoom in levels before zoom out levels zoomLevels = zoomInLevels ; zoomLevels . addAll ( zoomOutLevels ) ; break ; case OUT : case OUT_IN : // Order zoom out levels before zoom in levels zoomLevels = zoomOutLevels ; zoomLevels . addAll ( zoomInLevels ) ; break ; case CLOSEST_IN_OUT : case CLOSEST_OUT_IN : // Alternate the zoom in and out levels List < Long > firstLevels ; List < Long > secondLevels ; if ( type == TileScalingType . CLOSEST_IN_OUT ) { // Alternate starting with zoom in firstLevels = zoomInLevels ; secondLevels = zoomOutLevels ; } else { // Alternate starting with zoom out firstLevels = zoomOutLevels ; secondLevels = zoomInLevels ; } zoomLevels = new ArrayList <> ( ) ; int maxLevels = Math . max ( firstLevels . size ( ) , secondLevels . size ( ) ) ; for ( int i = 0 ; i < maxLevels ; i ++ ) { if ( i < firstLevels . size ( ) ) { zoomLevels . add ( firstLevels . get ( i ) ) ; } if ( i < secondLevels . size ( ) ) { zoomLevels . add ( secondLevels . get ( i ) ) ; } } break ; default : throw new GeoPackageException ( "Unsupported " + TileScalingType . class . getSimpleName ( ) + ": " + type ) ; } } } else { zoomLevels = new ArrayList <> ( ) ; } // Always check the request zoom level first zoomLevels . add ( 0 , requestZoomLevel ) ; // Build a list of tile matrices that exist for the zoom levels for ( long zoomLevel : zoomLevels ) { TileMatrix tileMatrix = tileDao . getTileMatrix ( zoomLevel ) ; if ( tileMatrix != null ) { tileMatrices . add ( tileMatrix ) ; } } } } return tileMatrices ; }


Input: Get the tile row results of tiles needed to draw the requested bounding box tile [CODESPLIT] private TileCursor retrieveTileResults ( BoundingBox projectedRequestBoundingBox , TileMatrix tileMatrix ) { TileCursor tileResults = null ; if ( tileMatrix != null ) { // Get the tile grid TileGrid tileGrid = TileBoundingBoxUtils . getTileGrid ( tileSetBoundingBox , tileMatrix . getMatrixWidth ( ) , tileMatrix . getMatrixHeight ( ) , projectedRequestBoundingBox ) ; // Query for matching tiles in the tile grid tileResults = tileDao . queryByTileGrid ( tileGrid , tileMatrix . getZoomLevel ( ) ) ; } return tileResults ; }


Input: Call after making changes to the point icon point radius or paint stroke widths . Determines the pixel overlap between tiles [CODESPLIT] public void calculateDrawOverlap ( ) { if ( pointIcon != null ) { heightOverlap = this . density * pointIcon . getHeight ( ) ; widthOverlap = this . density * pointIcon . getWidth ( ) ; } else { heightOverlap = this . density * pointRadius ; widthOverlap = this . density * pointRadius ; } float linePaintHalfStroke = this . density * lineStrokeWidth / 2.0f ; heightOverlap = Math . max ( heightOverlap , linePaintHalfStroke ) ; widthOverlap = Math . max ( widthOverlap , linePaintHalfStroke ) ; float polygonPaintHalfStroke = this . density * polygonStrokeWidth / 2.0f ; heightOverlap = Math . max ( heightOverlap , polygonPaintHalfStroke ) ; widthOverlap = Math . max ( widthOverlap , polygonPaintHalfStroke ) ; if ( featureTableStyles != null && featureTableStyles . has ( ) ) { // Style Rows Set < Long > styleRowIds = new HashSet <> ( ) ; List < Long > tableStyleIds = featureTableStyles . getAllTableStyleIds ( ) ; if ( tableStyleIds != null ) { styleRowIds . addAll ( tableStyleIds ) ; } List < Long > styleIds = featureTableStyles . getAllStyleIds ( ) ; if ( styleIds != null ) { styleRowIds . addAll ( styleIds ) ; } StyleDao styleDao = featureTableStyles . getStyleDao ( ) ; for ( long styleRowId : styleRowIds ) { StyleRow styleRow = styleDao . getRow ( styleDao . queryForIdRow ( styleRowId ) ) ; float styleHalfWidth = this . density * ( float ) ( styleRow . getWidthOrDefault ( ) / 2.0f ) ; widthOverlap = Math . max ( widthOverlap , styleHalfWidth ) ; heightOverlap = Math . max ( heightOverlap , styleHalfWidth ) ; } // Icon Rows Set < Long > iconRowIds = new HashSet <> ( ) ; List < Long > tableIconIds = featureTableStyles . getAllTableIconIds ( ) ; if ( tableIconIds != null ) { iconRowIds . addAll ( tableIconIds ) ; } List < Long > iconIds = featureTableStyles . getAllIconIds ( ) ; if ( iconIds != null ) { iconRowIds . addAll ( iconIds ) ; } IconDao iconDao = featureTableStyles . getIconDao ( ) ; for ( long iconRowId : iconRowIds ) { IconRow iconRow = iconDao . getRow ( iconDao . queryForIdRow ( iconRowId ) ) ; double [ ] iconDimensions = iconRow . getDerivedDimensions ( ) ; float iconWidth = this . density * ( float ) Math . ceil ( iconDimensions [ 0 ] ) ; float iconHeight = this . density * ( float ) Math . ceil ( iconDimensions [ 1 ] ) ; widthOverlap = Math . max ( widthOverlap , iconWidth ) ; heightOverlap = Math . max ( heightOverlap , iconHeight ) ; } } }


Input: Set the density [CODESPLIT] public void setDensity ( float density ) { this . density = density ; linePaint . setStrokeWidth ( this . density * lineStrokeWidth ) ; polygonPaint . setStrokeWidth ( this . density * polygonStrokeWidth ) ; featurePaintCache . clear ( ) ; }


Input: Set the line paint [CODESPLIT] public void setLinePaint ( Paint linePaint ) { if ( linePaint == null ) { throw new AssertionError ( "Line Paint can not be null" ) ; } this . linePaint = linePaint ; setLineStrokeWidth ( linePaint . getStrokeWidth ( ) ) ; }


Input: Set the polygon paint [CODESPLIT] public void setPolygonPaint ( Paint polygonPaint ) { if ( polygonPaint == null ) { throw new AssertionError ( "Polygon Paint can not be null" ) ; } this . polygonPaint = polygonPaint ; setPolygonStrokeWidth ( polygonPaint . getStrokeWidth ( ) ) ; }


Input: Draw the tile and get the bytes from the x y and zoom level [CODESPLIT] public byte [ ] drawTileBytes ( int x , int y , int zoom ) { Bitmap bitmap = drawTile ( x , y , zoom ) ; byte [ ] tileData = null ; // Convert the bitmap to bytes if ( bitmap != null ) { try { tileData = BitmapConverter . toBytes ( bitmap , compressFormat ) ; } catch ( IOException e ) { Log . e ( FeatureTiles . class . getSimpleName ( ) , "Failed to create tile. x: " + x + ", y: " + y + ", zoom: " + zoom , e ) ; } finally { bitmap . recycle ( ) ; } } return tileData ; }