package jeql.std.geom;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import jeql.api.function.FunctionClass;
public class GridFunction
implements FunctionClass
{
// hexagonal constant = height of hexagon of side 1
private static final double HEX_HGT = Math.sqrt(3.0);
public static int hexIndex(Geometry pt, Geometry extent, int nCellsX)
{
double envW = extent.getEnvelopeInternal().getWidth();
double cellSide = envW / (nCellsX -1) / 1.5;
Coordinate coord = pt.getCoordinate();
// transform coordinates so hex cell side length is 1
double x1 = (coord.x - extent.getEnvelopeInternal().getMinX()) / cellSide;
double y1 = (coord.y - extent.getEnvelopeInternal().getMinY()) / cellSide;
// transform so hex squares have side = 1
// and compute base index for hex square
double xp = (x1 + 1) / 1.5;
int ixp = (int) xp;
boolean isxpOdd = (ixp % 2) == 1;
double yp = y1 / HEX_HGT;
if (! isxpOdd) {
yp += 0.5;
}
int iyp = (int) yp;
// internal coordinates for hex square
double u = xp - ixp;
double v = yp - iyp;
// index adjustment values inside hex square
int dx = 0;
int dy = 0;
// compute adjustment values for hex square left upper and lower corners
if (3 * u <= 1.0) {
// lower left corner
if (v < 0.5
&& 3.0 * u + 2.0 * v < 1.0) {
dx = -1;
dy = isxpOdd ? 0 : -1;
}
// upper left corner
else if (v > 0.5
&& 3.0 * u < 2.0 * (v - 0.5)) {
dx = -1;
dy = isxpOdd ? 1 : 0;
}
}
// adjust to get final hex cell coordinates
int I = ixp + dx;
int J = iyp + dy;
// convert to single numeric index (row-major order)
int index = I + nCellsX * J;
return index;
}
public static Geometry hexGeom(int index, Geometry extent, int nCellsX)
{
double envW = extent.getEnvelopeInternal().getWidth();
double minx = extent.getEnvelopeInternal().getMinX();
double miny = extent.getEnvelopeInternal().getMinY();
double cellSide = envW / (nCellsX -1) / 1.5;
int J = index / nCellsX;
int I = index % nCellsX;
double xp = -1 + 1.5 * I;
double yp = HEX_HGT * J;
if (I % 2 == 0)
yp -= HEX_HGT / 2.0;
double x = minx + cellSide * xp;
double y = miny + cellSide * yp;
double hh = cellSide * HEX_HGT;
Coordinate[] pts = new Coordinate[] {
new Coordinate(x + 0.5 * cellSide, y),
new Coordinate(x, y + hh / 2),
new Coordinate(x + 0.5 * cellSide, y + hh),
new Coordinate(x + 1.5 * cellSide, y + hh),
new Coordinate(x + 2 * cellSide, y + hh / 2),
new Coordinate(x + 1.5 * cellSide, y),
new Coordinate(x + 0.5 * cellSide, y)
};
return GeomFunction.geomFactory.createPolygon(
GeomFunction.geomFactory.createLinearRing(pts), null);
}
}