com.dataartisans.flinktraining.exercises.datastream_java.utils.GeoUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of flink-training-exercises Show documentation
Show all versions of flink-training-exercises Show documentation
Utilities and material for an Apache Flink Training provided by data Artisans.
The newest version!
/*
* Copyright 2015 data Artisans GmbH
*
* 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 com.dataartisans.flinktraining.exercises.datastream_java.utils;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* GeoUtils provides utility methods to deal with locations for the data streaming exercises.
*/
public class GeoUtils {
// geo boundaries of the area of NYC
public static double LON_EAST = -73.7;
public static double LON_WEST = -74.05;
public static double LAT_NORTH = 41.0;
public static double LAT_SOUTH = 40.5;
// area width and height
public static double LON_WIDTH = 74.05 - 73.7;
public static double LAT_HEIGHT = 41.0 - 40.5;
// delta step to create artificial grid overlay of NYC
public static double DELTA_LON = 0.0014;
public static double DELTA_LAT = 0.00125;
// ( |LON_WEST| - |LON_EAST| ) / DELTA_LAT
public static int NUMBER_OF_GRID_X = 250;
// ( LAT_NORTH - LAT_SOUTH ) / DELTA_LON
public static int NUMBER_OF_GRID_Y = 400;
public static float DEG_LEN = 110.25f;
/**
* Checks if a location specified by longitude and latitude values is
* within the geo boundaries of New York City.
*
* @param lon longitude of the location to check
* @param lat latitude of the location to check
*
* @return true if the location is within NYC boundaries, otherwise false.
*/
public static boolean isInNYC(float lon, float lat) {
return !(lon > LON_EAST || lon < LON_WEST) &&
!(lat > LAT_NORTH || lat < LAT_SOUTH);
}
/**
* Maps a location specified by latitude and longitude values to a cell of a
* grid covering the area of NYC.
* The grid cells are roughly 100 x 100 m and sequentially number from north-west
* to south-east starting by zero.
*
* @param lon longitude of the location to map
* @param lat latitude of the location to map
*
* @return id of mapped grid cell.
*/
public static int mapToGridCell(float lon, float lat) {
int xIndex = (int)Math.floor((Math.abs(LON_WEST) - Math.abs(lon)) / DELTA_LON);
int yIndex = (int)Math.floor((LAT_NORTH - lat) / DELTA_LAT);
return xIndex + (yIndex * NUMBER_OF_GRID_X);
}
/**
* Maps the direct path between two locations specified by longitude and latitude to a list of
* cells of a grid covering the area of NYC.
* The grid cells are roughly 100 x 100 m and sequentially number from north-west
* to south-east starting by zero.
*
* @param lon1 longitude of the first location
* @param lat1 latitude of the first location
* @param lon2 longitude of the second location
* @param lat2 latitude of the second location
*
* @return A list of cell ids
*/
public static List mapToGridCellsOnWay(float lon1, float lat1, float lon2, float lat2) {
int x1 = (int)Math.floor((Math.abs(LON_WEST) - Math.abs(lon1)) / DELTA_LON);
int y1 = (int)Math.floor((LAT_NORTH - lat1) / DELTA_LAT);
int x2 = (int)Math.floor((Math.abs(LON_WEST) - Math.abs(lon2)) / DELTA_LON);
int y2 = (int)Math.floor((LAT_NORTH - lat2) / DELTA_LAT);
int startX, startY, endX, endY;
if(x1 <= x2) {
startX = x1;
startY = y1;
endX = x2;
endY = y2;
}
else {
startX = x2;
startY = y2;
endX = x1;
endY = y1;
}
double slope = (endY - startY) / ((endX - startX)+0.00000001);
int curX = startX;
int curY = startY;
ArrayList cellIds = new ArrayList<>(64);
cellIds.add(curX + (curY * NUMBER_OF_GRID_X));
while(curX < endX || curY != endY) {
if(slope > 0) {
double y = (curX - startX + 0.5) * slope + startY - 0.5;
if(y > curY - 0.05 && y < curY + 0.05) {
curX++;
curY++;
}
else if(y < curY) {
curX++;
}
else {
curY++;
}
}
else {
double y = (curX - startX + 0.5) * slope + startY + 0.5;
if(y > curY - 0.05 && y < curY + 0.05) {
curX++;
curY--;
}
if(y > curY) {
curX++;
}
else {
curY--;
}
}
cellIds.add(curX + (curY * NUMBER_OF_GRID_X));
}
return cellIds;
}
/**
* Returns the longitude of the center of a grid cell.
*
* @param gridCellId The grid cell.
*
* @return The longitude value of the cell's center.
*/
public static float getGridCellCenterLon(int gridCellId) {
int xIndex = gridCellId % NUMBER_OF_GRID_X;
return (float)(Math.abs(LON_WEST) - (xIndex * DELTA_LON) - (DELTA_LON / 2)) * -1.0f;
}
/**
* Returns the latitude of the center of a grid cell.
*
* @param gridCellId The grid cell.
*
* @return The latitude value of the cell's center.
*/
public static float getGridCellCenterLat(int gridCellId) {
int xIndex = gridCellId % NUMBER_OF_GRID_X;
int yIndex = (gridCellId - xIndex) / NUMBER_OF_GRID_X;
return (float)(LAT_NORTH - (yIndex * DELTA_LAT) - (DELTA_LAT / 2));
}
/**
* Returns a random longitude within the NYC area.
*
* @param rand A random number generator.
* @return A random longitude value within the NYC area.
*/
public static float getRandomNYCLon(Random rand) {
return (float)(LON_EAST - (LON_WIDTH * rand.nextFloat()));
}
/**
* Returns a random latitude within the NYC area.
*
* @param rand A random number generator.
* @return A random latitude value within the NYC area.
*/
public static float getRandomNYCLat(Random rand) {
return (float)(LAT_SOUTH + (LAT_HEIGHT * rand.nextFloat()));
}
/**
* Returns the Euclidean distance between two locations specified as lon/lat pairs.
*
* @param lon1 Longitude of first location
* @param lat1 Latitude of first location
* @param lon2 Longitude of second location
* @param lat2 Latitude of second location
* @return The Euclidean distance between the specified locations.
*/
public static double getEuclideanDistance(float lon1, float lat1, float lon2, float lat2) {
double x = lat1 - lat2;
double y = (lon1 - lon2) * Math.cos(lat2);
return (DEG_LEN * Math.sqrt(x*x + y*y));
}
/**
* Returns the angle in degrees between the vector from the start to the destination
* and the x-axis on which the start is located.
*
* The angle describes in which direction the destination is located from the start, i.e.,
* 0° -> East, 90° -> South, 180° -> West, 270° -> North
*
* @param startLon longitude of start location
* @param startLat latitude of start location
* @param destLon longitude of destination
* @param destLat latitude of destination
* @return The direction from start to destination location
*/
public static int getDirectionAngle(
float startLon, float startLat, float destLon, float destLat) {
double x = destLat - startLat;
double y = (destLon - startLon) * Math.cos(startLat);
int degrees = (int)Math.toDegrees(Math.atan2(x, y)) + 179;
return degrees;
}
}