Algorithm for Creating user Defined Geofences - java

I've got a latitude & longitude of a point. I want all the readings of latitude & longitude within a radius of 500M with respect to that given point. Is any method for that? Is it possible? Is there any algorithm for it?

There are many formulas available to calculate the distance between two lat/long points (it won't be exact due to altitude variation, but very close), and filter your sample points based on distance from your given point.
A nice overview of what's available (with math and source code) is available here: http://www.movable-type.co.uk/scripts/latlong.html
Browse through there and pick the distance formula that fits your needs the best.

Here's a solution on StackOverflow for finding the distance between 2 locations, by Usman Kurd
https://stackoverflow.com/a/14394403/2128327
So with a little tweak, we can use his function:
public double getKmDistance(GeoPoint StartP, GeoPoint EndP) {
int Radius=6371;//radius of earth in Km
double lat1 = StartP.getLatitudeE6()/1E6;
double lat2 = EndP.getLatitudeE6()/1E6;
double lon1 = StartP.getLongitudeE6()/1E6;
double lon2 = EndP.getLongitudeE6()/1E6;
double dLat = Math.toRadians(lat2-lat1);
double dLon = Math.toRadians(lon2-lon1);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult= Radius*c;
double km=valueResult/1;
DecimalFormat newFormat = new DecimalFormat("####");
kmInDec = Integer.valueOf(newFormat.format(km));
meter=valueResult%1000;
meterInDec= Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value",""+valueResult+" KM "+kmInDec+" Meter "+meterInDec);
return kmInDec;
}
then let's say that you have a list of locations:
ArrayList<GeoPoint> geoPoints = new ArrayList<GeoPoint>();
And we have our current location:
GeoPoint currentLocation = new GeoPoint(..);
then you can do this:
ArrayList<GeoPoint> within500Km = new ArrayList<GeoPoint>();
for (GeoPoint g : geoPoints)
if (getKmDistance(currentLocation, g) <= 500.0)
within500Km.add(g);
for(GeoPoint g : within500Km)
System.out.println("> "+g.getLatitudeE6()+" : "+g.getLongitudeE6()+" ");

Related

calculate distance between two place using latitude-longitude getting wrong distance in java

i am using haversine formula to calculate distance but i am getting wrong distance actually google map distance is 8.1km but haversine formula is showing 4.06
private static final int EARTH_RADIUS = 6371; // Approx Earth radius in KM
public static double distance(double startLat, double startLong, double endLat, double endLong) {
double dLat = Math.toRadians((endLat - startLat));
double dLong = Math.toRadians((endLong - startLong));
startLat = Math.toRadians(startLat);
endLat = Math.toRadians(endLat);
double a = haversin(dLat) + Math.cos(startLat) * Math.cos(endLat) * haversin(dLong);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return EARTH_RADIUS * c; // <-- d
}
public static double haversin(double val) {
return Math.pow(Math.sin(val / 2), 2);
}
Your formula is correct, the problem come from bad use of google map
As suggested by Tim in comments, you need to see the point-to-point distance, not road distance
Using the two distance(17.451955, 78.478187, 17.442504, 78.441323) give 4.06km:
8.1km is probably the distance by road, and not point-to-point

Java - Calculate second coordinates from a given coordinates, bearing, and distance

I found the formula to calculate the second coordinates here. But when I converted it to Java, the result is not as I expected.
private Point get(double lat1, double lon1, double tc, int d) {
double lat = Math.asin(
Math.sin(lat1) * Math.cos(d)
+ Math.cos(lat1) * Math.sin(d) * Math.cos(tc)
);
double dlon= Math.atan2(
Math.sin(tc) * Math.sin(d) * Math.cos(lat1)
, Math.cos(d) - Math.sin(lat1) * Math.sin(lat));
double lon = ((lon1 - dlon + Math.PI) % (2 * Math.PI)) - Math.PI;
return new Point(lat, lon);
}
I tested the code above with simple case such as get(50, 10, 0, 0). So expected the result will be as same as the first point, but this is the result I got:
Lat: 1.4432701894877245, lon: -3.8108244707674395
Am I using correct formula to calculate second coordinates?
[EDIT]
Here is the formula that I try to convert to java code
lat =asin(sin(lat1)*cos(d)+cos(lat1)*sin(d)*cos(tc))
dlon=atan2(sin(tc)*sin(d)*cos(lat1),cos(d)-sin(lat1)*sin(lat))
lon=mod( lon1-dlon +pi,2*pi )-pi
As noted in comments, your formulas expect that the latitude, longitude, true course, and distance are all in radians.
If you want to pass in latitude, longitude, true course in degrees, and distance in nautical miles, you will need to do the following conversion below any math:
// convert to radians
lat1 = lat1 * Math.PI / 180;
lon1 = lon1 * Math.PI / 180;
tc = tc * Math.PI / 180;
d = (Math.PI / (180*60)) * d;
and then convert your latitude and longitude back from radians to degrees:
// convert to degrees
lat = lat * 180 / Math.PI;
lon = lon * 180 / Math.PI;
However, two other notes:
1) java.awt.Point (not clear this is what you're using) can only hold integers; you might want to use Point2D.Double instead; and
2) Distance should also be measured including fractions of either nautical miles or radians, so should be a double.
With those edits, get(50, 10, 0, 0) will work. As will the worked example from your page for a waypoint 100nm from LAX on the 66 degree radial - get(33.95, 118.4, 66, 100) (remember that minutes are converted into fractional degrees) returns 34.6141 lat and 116.5499 lon, matching 34d 37m and 116d 33m.

Distance between a Lat/Long & the closest edge of a polygon which is made up of Lat/Longs?

I have a list of Lat/Long coordinates that represents a polygon and a single separate Lat/Long which I know is contained within the polygon.
How do I determine the distance from the single Lat/Long to the closest edge of the polygon? Is there a known Java library for this?
I suggest following solution, which also works in case of a polygon that is around the north pole, where a calculation of the longitude and latitude difference doesn't make sense.
The solution transforms the longitude and latitude of points on the earth into three-dimensional coordinates by using the World Geodetic System 84. With those three-dimensional points, you can calculate the projection of one point on the line defined by two other points in three-dimensional space.
Here is the code doing the calculations. It uses the class javafx.geometry.Point3D, available in Java 8.
/** Semi-major axis of earth in meter */
public static final double WGS84_A = 6378137.0;
/** Semi-minor axis of earth in meter */
public static final double WGS84_B = 6356752.314245;
/** Eccentricity of earth */
public static final double WGS84_E =
Math.sqrt( (WGS84_A * WGS84_A) / (WGS84_B * WGS84_B) - 1);
public static final double DEGREES_TO_RADIANS = Math.PI / 180;
/**
* Calculates a three-dimensional point in the
* World Geodetic System (WGS84) from latitude and longitude.
*/
public static Point3D latLonToPoint3D(double lat, double lon) {
double clat = Math.cos(lat * DEGREES_TO_RADIANS);
double slat = Math.sin(lat * DEGREES_TO_RADIANS);
double clon = Math.cos(lon * DEGREES_TO_RADIANS);
double slon = Math.sin(lon * DEGREES_TO_RADIANS);
double N = WGS84_A / Math.sqrt(1.0 - WGS84_E * WGS84_E * slat * slat);
double x = N * clat * clon;
double y = N * clat * slon;
double z = N * (1.0 - WGS84_E * WGS84_E) * slat;
return new Point3D(x, y, z);
}
/**
* Calculates distance of projection p of vector a on vector b.
*
* Use formula for projection, with p being the projection point:
* <p>
* p = a X b / |b|^2 * b
* </p>
* X being the dot product, * being multiplication of vector and constant
*/
public static Point3D calculateProjection(Point3D a, Point3D b) {
return b.multiply(a.dotProduct(b) / (b.dotProduct(b)));
}
/**
* Calculates shortest distance of vector x and the line defined by
* the vectors a and b.
*/
public static double calculateDistanceToLine(Point3D x, Point3D a, Point3D b) {
Point3D projectionOntoLine =
calculateProjection(x.subtract(a), b.subtract(a)).add(a);
return projectionOntoLine.distance(x);
}
By calling calculateDistanceToLine with the point and the polygon segments' points, you are able to find the nearest line defined by the edge points and extended to infinity. In the case of a concave polygon, this may not be what you want, as you see in the picture.
Taking into account that the distance to the polygon edge must be at least as long as the distance to the nearest edge point, you can get the distance to the edge as:
Math.max(calculateDistanceToLine(x, edgePoint1, edgePoint2),
Math.min(x.distance(edgePoint1), x.distance(edgePoint2)));
Note that this calculation yields also not the distance on the surface of the earth, but the direct distance cutting through the earth. Anyway, it should suffice for choosing the shortest distance.
The function latLonToPoint3Dis a modified version of the function that I found here.
you can just loop through all your edges and calculate the distance between the two points like this:
function double calculateDistance(
double edgeLat1, double edgeLng1,
double edgeLat2, double edgeLng2,
double pointLat, double pointLng) {
//calculate straight/edge
double mS = (edgeLng2 - edgeLng1)/(edgeLat2- edgeLat2);
double tS = edgeLng1 - edgeLng1 * mS;
//calculate helper straight
double mH = -mS;
double tH = pointLng - mH * pointLat;
//calcuate straight intersection
xI = (tH - tS)/(mS - mH);
yI = mH * xI - tH;
//calculate distance
/* in degree
double dInDegree = Math.sqrt((pointLat - xI) * (pointLat - xI)
+ (pointLng - yI) * (pointLng - yI));
return dInDegree;
*/
//in meter
double R = 6371000; // m
double dLat = (pointLat-xI).toRad();
double dLon = (pointLng-yI).toRad();
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(x1.toRad()) * Math.cos(pointLat.toRad()) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double distanceInMeter = R * c;
return distanceInMeter;
}
I hope this works for you, this is "simple" vector maths.
Check the Single Separate Lat/Long, for the closest coordinate that exists in your list.
Then Gather the two points that are connected to that Coordinate(the one that is closest to your single point) So now you have 4 points.
singlePoint, closestPointToSinglePoint, neighbor1, neighbor2. I'm assuming you have some basic trig experience at this point(no pun intended). What you should do from here is visualize 2 triangles. (singlePoint, closestPointToSinglePoint, neighbor1) and (singlePoint, closestPointToSinglePoint, neighbor2).
At this point, calculate the height of the triangles from the SinglePoint as a reference. You now have 2 distances to the 2 closest edges. Compare, and enjoy your results.

How do I write a Java program that calculates the distance between two points on earth?

I know how to start it out and I know how to put in the scanners and everything, but in school, I've never really learned about longitude and latitude formulas and how to convert those points into radians. So I'm pretty much stuck on this Java problem. Here is what I have so far:
import java.util.*;
class DistanceCalculator {
// Radius of the earth in km; this is the class constant.
public static final double Radius = 6372.795;
/**
* This program computes the spherical distance between two points on the surface of the Earth.
*/
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
intro();
System.out.print("Longitude (degrees.minutes) ");
double Longitude = console.nextDouble();
System.out.print("Latitude (degrees.minutes) ");
double Latitude = console.nextDouble();
}
public static double distFrom(double lat1, double lng1, double lat2, double lng2);
double Latitude = Math.toRadians(...);
}
public static void intro() {
System.out.println("This program computes the spherical distance between two points on the surface of the Earth.");
System.out.println("\tPlease start by entering the longitude and the latitude of location 1.");
}
}
In Java IDE, they say that Longitude and Latitude points (the ones underneath the intro();) are not used, and I know why, since I haven't really defined them yet.
I know I'm missing the formula for longitude and latitude. In my book, it wants me to use the spherical law of cosines, and since I've never learned this at school, no matter how hard I study the formula from the websites I sought out, I don't know how to transfer that into Java language.
Another problem is, how do I transfer degrees and minutes from a longitude/latitude point into radians? Do I have to use Math.toRadians thing? Oh yeah and also, my answer has to be in kilometers.
Updated: The math functions some of you guys are talking about confuses me greatly. In school (I'm a high schooler), even at Math IB SL, my teacher has never taught us how to find long/lat. points...yet. So it's hard for me to grasp. Since the spherical law of cosines formula is online, do I basically just take that formula and convert it into "java language" and plug it into my program?
The key word you need to search for is the "Haversine formula".
An easier to understand method, but one which is not quite so accurate for small distances, is to recall that the angle between two vectors A and B can be calculated using the dot product:
A ⋅ B = |A| * |B| * cos(theta)
so if you convert your polar lat/long pairs into 3D cartesian coordinates (and yes, you'll need to use Math.toRadians(), Math.cos() and Math.sin() to do that, and then calculate the dot product, you'll then get cos(theta), so use Math.acos() to get theta.
You can then work out the distance simply as D = R * theta, where R is the radius of the Earth, and theta remains in radians.
I suggest to read more about WGS84.
Mathematical explanations here.
You may look at this link for the logic.
http://aravindtrue.wordpress.com/2009/06/30/calculate-distance-using-latitude-and-longitude-php-mysql/
Function in PHP... I don't know Java. So some one edit my post. Here is the PHP function:
function getDistanceBetweenPointsNew($latitude1, $longitude1,
$latitude2, $longitude2, $unit = 'Mi')
{
$theta = $longitude1 - $longitude2;
$distance = (sin(deg2rad($latitude1)) *
sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) *
cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
$distance = acos($distance);
$distance = rad2deg($distance);
$distance = $distance * 60 * 1.1515;
switch($unit)
{
case 'Mi': break;
case 'Km' : $distance = $distance *1.609344;
}
return (round($distance,2));
}
also to get value from MySQL database:
Calculate distance given 2 points, latitude and longitude
I tried to create a java function, I don't know if it work or not.
try this. If any one can help, try edit my java code.
import java.math.BigDecimal;
public static double round(double unrounded, int precision, int roundingMode)
{
BigDecimal bd = new BigDecimal(unrounded);
BigDecimal rounded = bd.setScale(precision, roundingMode);
return rounded.doubleValue();
}
public static double distFrom(double lat1, double lng1, double lat2, double lng2, String unit)
{
double theta = lng1 - lng2;
double distance = (
Math.sin(Math.toRadians(lat1)) * Math.sin(Math.toRadians(lat2))
)+(
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.cos(Math.toRadians(theta))
);
distance = Math.acos(distance);
distance = Math.toDeg(distance);
distance = distance * 60 * 1.1515;
switch(unit)
{
/* Mi = miles, Km = Kilometers */
case "Mi" :
break;
case "Km" :
distance = distance *1.609344;
break;
}
distance = round(distance, 2, BigDecimal.ROUND_HALF_UP);
return distance;
}
import java.util.*;
public class SphericalDistance {
public static void main(String[] args){
System.out.println(" This program computes the spherical distance\n between two points, 1 and 2.");
System.out.println(" Please enter the latitude and longitude for \n each point as a pair of integers, degrees \n followed by minutes:");
System.out.print("Latitude 1:");
Scanner s=new Scanner(System.in);
double latangledeg = s.nextDouble();
double latanglemin = s.nextDouble()/60;
double phideg = latangledeg + latanglemin;
double phi1 = phideg * Math.PI/180;
System.out.print("Longitude 1:");
double lonangledeg = s.nextDouble();
double lonanglemin = s.nextDouble()/60;
double lambdadeg = lonangledeg + lonanglemin;
double lambda1 = lambdadeg * Math.PI/180;
System.out.println("Latitude 2:");
double latangledeg2 = s.nextDouble();
double latanglemin2 = s.nextDouble()/60;
double phideg2 = latangledeg2 + latanglemin2;
double phi2 = phideg2 * Math.PI/180;
System.out.println("Longitude 2:");
double lonangledeg2 = s.nextDouble();
double lonanglemin2 = s.nextDouble()/60;
double lambdadeg2 = lonangledeg2 + lonanglemin2;
double lambda2 = lambdadeg2 * Math.PI/180;
double lambdaf = lambda2 - lambda1;
double angdistance = Math.acos(Math.sin(phi1)*Math.sin(phi2) + Math.cos(phi1)*Math.cos(phi2)*Math.cos(lambdaf));
System.out.println("Angular Distance = " + angdistance + " radians");
int distancekm = (int)(angdistance * 6372.795);
int distancemi = (int) (distancekm * .621371);
System.out.println("Distance = " + distancekm + " kilometers");
System.out.println("Distance = " + distancemi + " miles");
s.close();
}
}

Java - Trigonometry Hell

I have a task of being able to program a Class in Java to calculate the bearing from North to a point. The only objects that are known are 2 positions, both have a bearing from North and the distance from 0. So for example - position 1 - 30 degrees and 10m, position 2 - 190 degrees and 50m. How would you calculate the bearing if you wanted to travel from position 1 to position 2 for instance or from position 2 to 1? I can calculate the distance between the 2 positions using the cosine rule, but have no idea how to create a class that will accuratly calculate the bearing in different scenarios?
Any help or advise would be greatly appreciated.
From http://en.wikipedia.org/wiki/Law_of_cosines#Applications:
...once you have all three side lengths, this will give you the third angle of your triangle.
(The Haversine formula is for navigation on a sphere... I think we're just worried about vectors on a plane.)
I believe what you are looking for is the Haversine formula, googling it will yield implementations in various languages.
This is a java version ported from a javascript solution given here:
Using the Haversine Formula in Javascript by talkol
// this was a pojo class we used internally...
public class GisPostalCode {
private String country;
private String postalCode;
private double latitude;
private double longitude;
// getters/setters, etc.
}
public static double distanceBetweenCoordinatesInMiles2(GisPostalCode c1, GisPostalCode c2) {
double lat2 = c2.getLatitude();
double lon2 = c2.getLongitude();
double lat1 = c1.getLatitude();
double lon1 = c1.getLongitude();
double R = 6371; // km
double x1 = lat2 - lat1;
double dLat = x1 * Math.PI / 180;
double x2 = lon2 - lon1;
double dLon = x2 * Math.PI / 180;
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1*Math.PI/180) * Math.cos(lat2*Math.PI/180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double d = R * c;
// convert to miles
return d / 1.60934;
}

Categories