TileIndexCalculator.java
/*
* Copyright 2021 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.genesys.util;
/**
* Raster grid utilities.
*/
public class TileIndexCalculator {
/**
* Gets the 3x3 minute grid cell zero-based index starting in the NW corner
* (-180,90) with `tile=0` and ending in the SW corner (180,-90). A 3 minute
* grid has `ncol=7200` "columns" and `nrow=3600` "rows".
*
* @param longitude the longitude
* @param latitude the latitude
* @return the cell index for a 3 degree grid
*/
public static final Integer get3MinuteTileIndex(Number longitude, Number latitude) {
if (longitude == null || latitude == null)
return null;
if (longitude.doubleValue() < -180 || longitude.doubleValue() > 180)
return null;
if (latitude.doubleValue() < -90 || latitude.doubleValue() > 90)
return null;
final int columns = 7200;
final int rows = 3600;
final float xres_inv = columns / 360f;
final float yres_inv = rows / 180f;
// yx is offset by 0.5 * yd in
// https://github.com/rspatial/raster/blob/master/R/rasterFromBIL.R#L92
// I took two days to find out why math doesn't work out!
var ymax = 89.99990f; // 90.0d
int nrow;
if (latitude.intValue() == -90) {
nrow = (int) (rows) - 1;
} else if (latitude.intValue() == 90) {
nrow = 0;
} else {
nrow = (int) ((ymax - latitude.floatValue()) * yres_inv);
}
// longitude (-180:180) -> (0:columns-1)
int ncol = (int) ((longitude.floatValue() + 180f) * xres_inv);
if (longitude.intValue() == 180) {
ncol = (int) (columns - 1);
}
return nrow * columns + ncol;
}
}