Latitude / Longitude Distance Calculation - iphone

A quick question about a Lat / Long calculation.
I want to take a value set e.g. Lat: 55.123456 Long -6.123456 and work out the four points that are an arbitrary distance away.
As the given square, I want to work out the value for Latitude on the left and right side. Thus the red lines are 1.5km from the start point. Likewise for the longitude, the blue lines will be 1.5km from the start point. The output will be 4 points, all distances in kilometres.
In short: Latitude + Y = Latitude Value X kilometers away
Working with iPhone at the moment and its for a very rough database calculation.
EDIT: Just to clarify, the distance is so short that curvature (And hence accuracy) is not an issue.

In OBJ-C this should be a decent solution:
float r_earth = 6378 * 1000; //Work in meters for everything
float dy = 3000; //A point 3km away
float dx = 3000; //A point 3km away
float new_latitude = latitude + (dy / r_earth) * (180 / M_PI);
float new_longitude = longitude + (dx / r_earth) * (180 / M_PI) / cos(latitude * 180/M_PI);

Well, for rough calculation with relatively small distances (less than 100km) you may assume that there is 40_000_000/360=111 111 meters per degree of latitude and 111 111*cos(latitude) meters per degree of longitude. This is because a meter was defined as 1/40_000_000 part of the Paris meridian;).
Otherwise you should use great circle distances, as noted in the comments. For high precision you also need to take into account that Earth is slightly oblate spheroid rather than a sphere.

// parameter: offset in meters
float offsetM = 1500; // 1.5km
// degrees / earth circumfence
float degreesPerMeter = 360.0 / 40 000 000;
float toRad = 180 / M_PI;
float latOffsetMeters = offsetM * degreesPerMeter;
float lonOffsetMeters = offsetM * degreesPerMeter * cos (centerLatitude * toRad);
Now simply add +/- latOffsetMeters and +/- lonOffsetMeters to your centerLatitude/ centerLongitude.
Formula is usefull up to hundred kilometers.

Related

How get distance in degrees to calculate buffers in athena?

Athena only allows to calculate the distance of the buffer in decimal degrees but this value varies with respect to the latitude in the globe, tate to obtain a distance according to the following formula but it is not consistent in Mexico.
Athena function like this : ST_Buffer(geometry, double)
Athena geospatial functions
So, is posible obtain the corresponding distance in decimal degrees over a custom point in map , ex : get the decimal degree for point x, y like that distance in meters is 300 mts
Currently I use the following formula to approximate the decimal degrees but some buffers are quite horrible although it meets the minimum required
SELECT
ST_Buffer(ST_GeometryFromText( shape_wkt) ,
abs(5000.0 * 360.0 / (2.0 * pi() * cos( latitud )* 6400000.0) ) ) AS
dinamic_buffer_5000
5000 is buffer in meters
6400000.0 earth radius in meters
Some useffull questions :
gps-coordinates-in-degrees-to-calculate-distances
Calculate distance in meters using results in degrees
calculating-latitude-longitude-x-miles-from-point
A possible alternative is the following
To obtain the decimal degrees relative to a point one could:
Generate a second point at a distance d for this you would have to implement this formula, where the bearing does not matter
With this second point calculate the distance in Athena that will return the distance in decimal degrees, as input for the buffer function.
As an approximate is good alternative
Now how implement the second point ?....Here is the formula
I will try to convert to SQL code if can :
After a test I realize that even with the difference of distance it is not possible to obtain the buffer in an optimal way.
In this case the distance to the lower point was 300 meters, after obtaining the distance in decimal degrees with Athena an oblate shape is obtained, it changes the degree of inclination of the point by 90 degrees but it only generates a slightly larger shape.
Destination point given distance and bearing from start point
Source code (zory im edit for test my sql ):
destinationPoint(distance, bearing, radius=6371e3) {
// sinφ2 = sinφ1⋅cosδ + cosφ1⋅sinδ⋅cosθ
// tanΔλ = sinθ⋅sinδ⋅cosφ1 / cosδ−sinφ1⋅sinφ2
// see mathforum.org/library/drmath/view/52049.html for derivation
const dist_ang = distance / radius; // angular distance in radians
const angulo = Number(bearing).toRadians();
const rad_lat = this.lat.toRadians();
const rad_lon = this.lon.toRadians();
console.log("distance", distance);
console.log("radius", radius);
console.log("angular distance in radians", dist_ang);
console.log("bearing", Number(bearing));
console.log("bearing angulo ", angulo );
console.log("lat.toRadians", rad_lat);
console.log("lon.toRadians", rad_lon);
console.log("lon",this.lon);
console.log("lat",this.lat);
const sinφ2 = Math.sin(rad_lat) * Math.cos(dist_ang) + Math.cos(rad_lat) * Math.sin(dist_ang) * Math.cos(angulo);
const φ2 = Math.asin(sinφ2); //lat
console.log("φ2",φ2); //lat
console.log("sinφ2",sinφ2);
const y = Math.sin(angulo) * Math.sin(dist_ang) * Math.cos(rad_lat);
const x = Math.cos(dist_ang) - Math.sin(rad_lat) * sinφ2;
console.log("y",y);
console.log("x",x);
const λ2 = rad_lon + Math.atan2(y, x); //lon
console.log("λ2",λ2);
const lat = φ2.toDegrees();//lat
const lon = λ2.toDegrees();//lon
console.log("lon2",lon);
console.log("lat2",lat);
return new LatLonSpherical(lat, lon);
}

Compute coordinates position with projection

Given 2 coordinates (point 1 and 2 in red) in WGS84 I need to find the coordinates of the point perpendicular (point 3) to the line at a given distance.
I could manage to make the math to compute this perpendicular point, but when displayed on the map, the point seems to be at a wrong place, probably because of the projection.
What I want on a map:
And what I have instead on the map:
How can I take into account the projection so that the point on the map appears perpendicular to the line? The algorithm below to compute the point comes from here: https://math.stackexchange.com/questions/93424/calculate-rectangle-coordinates-from-line-and-height
public static Coords ComputePerpendicularPoint(Coords first, Coords last, double distance)
{
double slope = -(last.Lon.Value - first.Lon.Value) / (last.Lat.Value - first.Lat.Value);
// number of km per degree = ~111km (111.32 in google maps, but range varies between 110.567km at the equator and 111.699km at the poles)
// 1km in degree = 1 / 111.32km = 0.0089
// 1m in degree = 0.0089 / 1000 = 0.0000089
distance = distance * 0.0000089 / 100; //0.0000089 => represents around 1m in wgs84. /100 because distance is in cm
double t = distance / Math.Sqrt(1 + (slope * slope));
Coords perp_coord = new Coords();
perp_coord.Lon = first.Lon + t;
perp_coord.Lat = first.Lat + (t * slope);
return perp_coord;
}
Thank you in advance!

Find Minimum/Maximum latitude and Longitude

My Question is how can i find minimum and maximum latitude and longitude of specific area (500 meter) from current location.
In my case, Such like i need to get X and Y CLLocation (latitude and longitude) from 500meter of area
See my image (sorry for this may be bad drawing )
I also have to tried to googling and i got link such like
How can i get minimum and maximum latitude and longitude using current location and radius?
But i don't know how it implement in my case.
Pleas help me in this issue.
NOTE : I do not want to use CLLocationDistance distance = [currentLocation distanceFromLocation:newLocation]; because it is not helpful in my case so..
If you don't need a really precise value, then use the approximation that 1 degree is 111 km. Based on this, you need to add and remove 0.0025 degrees to the current coordinates to get corners of the area you are looking for.
rectanglesidelengthmeters = 500
degreedeltalat = 0.001 * (rectanglesidelengthmeters / 2.0) * cos(current.lon)
degreedeltalon = 0.001 * (rectanglesidelengthmeters / 2.0) * cos(current.lat)
minlat = current.lat - degreedeltalat
maxlat = current.lat + degreedeltalat
minlon = current.lon - degreedeltalon
maxlon = current.lon + degreedeltalon
You may need to correct the result a little for staying in the -90 .. 90 range for latitude and -180 .. 180 range for longitude values but I think CLClocation will handle that for you too.
You have to do some radius calculation from current location in km.
double kilometers = 0.5;
double curve = ABS( (cos(2 * M_PI * location.coordinate.latitude / 360.0) ));
MKCoordinateSpan span;
span.latitudeDelta = kilometers/111; //like allprog said.
span.longitudeDelta = kilometers/(curve * 111);
MKCoordinateRegion region;
region.span = span;
region.center = location.coordinate;
[self.mapView setRegion:region animated:YES];
This way i set mapView to show distance region to 0.5 km.
EDIT:
Whoa, i digging in my old 'liked' question to show you some original answer, but found a better one below accepted one:
how to make mapview zoom to 5 mile radius of current location
Look at #Anurag answer
To get precise value you should try with
minLattitude = currentLattitude - (RadiusInKm/111.12);
maxLattitude = currentLattitude + (RadiusInKm/111.12);
Thus in your case RadiusInKm = 0.5
For finding in & max longitude data you need to follow the same thing but but you have to multiply the result with cosine function of latitude
I would do this way.
double accuracy = 0.1;//How accurate do you want. Smaller value, slower perform
double distance = 500;//Distance you want
Create infinite loop.
In the loop check whether distance is bigger than 500. If yes, break. If not, add 0.1 value to latitude or longitude.
Do above way to get Max longitude, max latitude, min longitude and min latitude.
Compare your DB, if CLLocation is inside of the value, then return.
I cannot say this is the best way to solve your problem. Because we are guessing value...If you know how to convert CLLocation from given distance, that is better!
This should be correct (in php)
https://www.movable-type.co.uk/scripts/latlong-db.html
$R = 6371; // earth's mean radius, km
$rad = 0.5
// first-cut bounding box (in degrees)
$maxLat = $lat + rad2deg($rad/$R);
$minLat = $lat - rad2deg($rad/$R);
$maxLon = $lon + rad2deg(asin($rad/$R) / cos(deg2rad($lat)));
$minLon = $lon - rad2deg(asin($rad/$R) / cos(deg2rad($lat)));

Calculate Latitude and longitude more between Latitude/Longitude points?

Latitude: 22.744812,
Longitude: 75.892578
The above would be considered my center point.
And now I need to determine the latitude and longitude points from center point 1000 meter outward to each NSWE corners. So I would have a central long/lat, N, S, E and W long/lat..
So I would end up with 4 additional lat/long pairs.
What I am trying to resolve is a formula, preferably that can be done on a standard calculator to determine these 4 NSWE points based on the central point.
You could use MapKit for that:
- (CLLocationCoordinate2D *) calculateSquareCoordinates:(CLLocation*)center withRadius:(float)radius{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(center.coordinate, radius*2, radius*2);
CLLocationCoordinate2D points[4];
points[0] = CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta/2, region.center.longitude - region.span.longitudeDelta/2);
points[1] = CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta/2, region.center.longitude - region.span.longitudeDelta/2);
points[2] = CLLocationCoordinate2DMake(region.center.latitude + region.span.latitudeDelta/2, region.center.longitude + region.span.longitudeDelta/2);
points[3] = CLLocationCoordinate2DMake(region.center.latitude - region.span.latitudeDelta/2, region.center.longitude + region.span.longitudeDelta/2);
return points;
}
and just call
CLLocationCoordinate2D *fourPoints = [self calculateSquareCoordinates:center withRadius:1000];
on your code.
you will have to use the Haversine formula to calculate the Lat/Long based on distance from a starting Lat/Long. have a look at this Link
The average radius of the earth is around 6371000 metres. This means that
1 degree of lattitude is equivalent to 6371000 * PI / 180 metres
(NB: PI = 3.14159... etc). However, 1 degree of longitude depends on the lattitude that you are. At the equator, one degree of longitude corresponds to the same distance in metres as 1 degree of lattitude. However, at the north and south poles, all longitude values are the same point (i.e. the pole itself), so 1 degree of longitude at the poles is zero metres. The formula for longitude is
1 degree of longitude is equivalent to 637100 * PI / 180 * COS(Lattitude)
where COS is the trigonometric cosine function. If you make these conversions, then you can do the calculation on a standard calculator. However, be aware that these are approximations that work well over short distances (e.g. less than a few hundred kilometers), but over long distances (e.g. thousands of kilometers) they become more and more inaccurate.

MKCoordinateSpan in Meters?

I need to create a MKCoordinateSpan that is about 500 meters.
How do I calculate the values to pass into the MKCoordinateSpan constructor?
Answers in any programming (Obj-C, .Net) language are fine.
Another alternative is to use MapKit's MKCoordinateRegionMakeWithDistance function:
MKCoordinateRegion rgn = MKCoordinateRegionMakeWithDistance(
CLLocationCoordinate2DMake(someLatitude, someLongitude), 500, 500);
The MKCoordinateSpan will be in rgn.span.
Unless you need great accuracy you can make it much easier with approximation. The first problem is to find the fraction of a degree of latitude representing 500 meters. Easy since a degree of latitude is a constant in any location, roughly 111 km. So 500 meters is .0045 degrees latitude.
Then it gets harder because length of a degree of longitude varies depending on where you are. It can be approximated with
where alpha is earth's equatorial radius, 6,378,137km, b/a is 0.99664719 (a constant in use for the WGC84 spheroid model in use by all GPS devices) and where phi is the degree of latitude.
Imagine for a second you're lucky enough to be in Melbourne with a longitude of 37.783 degrees S. North or South doesn't matter here. beta works out to be 37.6899 and the rest of it solves to give a longitudinal degree a length of 88km. So 500 meters is .0057 of a degree.
Result for Melbourne - MKCoordinateSpan melbourne500MeterSpan = MKCoordinateSpanMake(.0045, .0057);
You can check your answers and your code with this online calculator
The wiki article on longitude has a lot more detail on this (and it the source of the images here)
Code:
#define EARTH_EQUATORIAL_RADIUS (6378137.0)
#define WGS84_CONSTANT (0.99664719)
#define degreesToRadians(x) (M_PI * (x) / 180.0)
// accepts decimal degrees. Convert from HMS first if that's what you have
double spanOfMetersAtDegreeLongitude(double degrees, double meters) {
double tanDegrees = tanf(degreesToRadians(degrees));
double beta = tanDegrees * WGS84_CONSTANT;
double lengthOfDegree = cos(atan(beta)) * EARTH_EQUATORIAL_RADIUS * M_PI / 180.0;
double measuresInDegreeLength = lengthOfDegree / meters;
return 1.0 / measuresInDegreeLength;
}
In MonoTouch, then using this solution you can use this helper method:
public static void ZoomToCoordinateAndCenter (MKMapView mapView, CLLocationCoordinate2D coordinate, double meters, bool showUserLocationToo, bool animate)
{
if (!coordinate.IsValid ())
return;
mapView.SetCenterCoordinate (coordinate, animate);
mapView.SetRegion (MKCoordinateRegion.FromDistance (coordinate, meters, meters), animate);
}