Skip to content

Instantly share code, notes, and snippets.

@randallwhitman
Last active December 17, 2015 17:19
Show Gist options
  • Save randallwhitman/5645293 to your computer and use it in GitHub Desktop.
Save randallwhitman/5645293 to your computer and use it in GitHub Desktop.
Trip Discovery - Equal-Angle Grid
@Override
public void setup(Context context)
{
// first pull values from the configuration
Configuration config = context.getConfiguration();
int minutes = config.getInt("com.esri.trip.threshold", 15); //minutes stoppage delineating trips
threshold = minutes * 60; // minutes -> seconds
double gridSide = 1000.; // Nominal/average/target length of side of grid cell (meters)
String sizeArg = config.get("com.esri.trip.cellsize", "1000");
if (sizeArg.length() > 0 && sizeArg.charAt(0) != '-') {
double trySize = Double.parseDouble(sizeArg);
if (trySize >= 100) //likely unrealistic smaller than about 200m to 500m
gridSide = trySize; // input as meters
else if (trySize > 0)
gridSide = 1000 * trySize; // input as km
}
String featuresPath = config.get("com.esri.trip.input");
FSDataInputStream iStream = null;
spatialReference = SpatialReference.create(4301); // GCS_Tokyo
try {
// load the JSON file provided as argument
FileSystem hdfs = FileSystem.get(config);
iStream = hdfs.open(new Path(featuresPath));
country = EsriFeatureClass.fromJson(iStream);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (iStream != null)
{
try {
iStream.close();
} catch (IOException e) { }
}
}
// build the grid of cells
if (country != null) {
envelope = new Envelope();
country.features[0].geometry.queryEnvelope(envelope);
buildGrid(gridSide);
}
}
private void buildGrid(double gridSide) { // Nominal length of side of grid cell (meters)
double cellArea = gridSide*gridSide;
latMax = envelope.getYMax() + .005; // +.005 to catch nearby outliers
latMin = envelope.getYMin() - .005; // -.005 to catch nearby outliers
final double latMid = (latMax + latMin) / 2; // idea: latitude of half area (ctry or envp?)
latExtent = latMax-latMin;
lonMin = envelope.getXMin() - .005; // -.005 to catch nearby outliers (approx. 500m)
lonMax = envelope.getXMax() + .005; // +.005 to catch nearby outliers
final double lonOneDeg = lonMin + 1; // arbitrary longitude for establishing lenOneDegBaseline
Point fromPt = new Point(lonMin, latMid),
toPt = new Point(lonOneDeg, latMid);
// geodesicDistanceOnWGS84 is an approximation as we are using a different GCS, but expect it
// to be a good approximation as we are using proportions only, not positions, with it.
final double lenOneDegBaseline = GeometryEngine.geodesicDistanceOnWGS84(fromPt, toPt);
// GeometryEngine.distance "Calculates the 2D planar distance between two geometries."
//angle// final double lenOneDegBaseline = GeometryEngine.distance(fromPt, toPt, spatialReference);
arcLon = gridSide / lenOneDegBaseline; // longitude arc of grid cell
final double latOneDeg = latMid + 1;
toPt.setXY(lonMin, latOneDeg);
final double htOneDeg = GeometryEngine.geodesicDistanceOnWGS84(fromPt, toPt);
int enough = (int)(Math.ceil(.000001 + (lonMax-lonMin)*lenOneDegBaseline/gridSide)) *
(int)(Math.ceil(.000001 + latExtent*htOneDeg/gridSide));
grid = new ArrayList<double[]>(enough);
double xlon, ylat;
// If using quadtree, could filter out cells that do not overlap country polygon
for (ylat = latMin, yCount = 0; ylat < latMax; yCount++) {
fromPt.setXY(lonMin, ylat);
toPt.setXY(lonMin+arcLon, ylat);
double xlen = GeometryEngine.geodesicDistanceOnWGS84(fromPt, toPt);
double height = cellArea/xlen; // meters
double arcLat = height / htOneDeg;
for (xlon = lonMin, xCount = 0; xlon < lonMax; xlon += arcLon, xCount++) {
double[] tmp = {xlon, ylat, xlon+arcLon, ylat+arcLat};
grid.add(tmp);
}
ylat += arcLat;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment