Calculate New Coordinates with Starting Position and Distance

Calculate new coordinates with starting position and distance

Ok, after some more digging, I found this answer, which resolves my problem. Here is my complete solution in swift:

internal func moveToLocation(location: CLLocationCoordinate2D, distance: Double) {
let angle = self.calculateAngleBetweenLocations(self.currentLocation, targetLocation: location)
let newLocation = self.coordinates(self.currentLocation, atDistance: distance, atAngle: angle)

self.moveUser(newLocation: newLocation)
}

private func coordinates(startingCoordinates: CLLocationCoordinate2D, atDistance: Double, atAngle: Double) -> CLLocationCoordinate2D {
let distanceRadians = atDistance / 6371
let bearingRadians = self.degreesToRadians(atAngle)
let fromLatRadians = self.degreesToRadians(startingCoordinates.latitude)
let fromLonRadians = self.degreesToRadians(startingCoordinates.longitude)

let toLatRadians = asin(sin(fromLatRadians) * cos(distanceRadians) + cos(fromLatRadians) * sin(distanceRadians) * cos(bearingRadians))
var toLonRadians = fromLonRadians + atan2(sin(bearingRadians) * sin(distanceRadians) * cos(fromLatRadians), cos(distanceRadians) - sin(fromLatRadians) * sin(toLatRadians));

toLonRadians = fmod((toLonRadians + 3 * M_PI), (2 * M_PI)) - M_PI

let lat = self.radiansToDegrees(toLatRadians)
let lon = self.radiansToDegrees(toLonRadians)

return CLLocationCoordinate2D(latitude: lat, longitude: lon)
}

private func calculateAngleBetweenLocations(currentLocation: CLLocationCoordinate2D, targetLocation: CLLocationCoordinate2D) -> Double {
let fLat = self.degreesToRadians(currentLocation.latitude);
let fLng = self.degreesToRadians(currentLocation.longitude);
let tLat = self.degreesToRadians(targetLocation.latitude);
let tLng = self.degreesToRadians(targetLocation.longitude);
let deltaLng = tLng - fLng

let y = sin(deltaLng) * cos(tLat)
let x = cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(deltaLng)

let bearing = atan2(y, x)

return self.radiansToDegrees(bearing)
}

private func degreesToRadians(x: Double) -> Double {
return M_PI * x / 180.0
}

private func radiansToDegrees(x: Double) -> Double {
return x * 180.0 / M_PI
}

Calculate new coordinate with given coordinate and distance in meters

One way would be to define helper methods that make it easy to calculate new coordinates based on a coordinate given a distance in meters using the MapKit and CoreLoation like so:

// Create new coordinate with equal latitude and longitude distances (distance can be both positive and negative).
func coordinate(from coordinate: CLLocationCoordinate2D, distance: CLLocationDistance) -> CLLocationCoordinate2D {
return self.coordinate(from: coordinate, latitudeDistance: distance, longitudeDistance: distance)
}

// Create new coordinate with latitude and longitude distances (distances can be both positive and negative).
func coordinate(from coordinate: CLLocationCoordinate2D, latitudeDistance: CLLocationDistance, longitudeDistance: CLLocationDistance) -> CLLocationCoordinate2D {
let region = MKCoordinateRegionMakeWithDistance(coordinate, latitudeDistance, longitudeDistance)

let newLatitude = coordinate.latitude + region.span.latitudeDelta
let newLongitude = coordinate.longitude + region.span.longitudeDelta

return CLLocationCoordinate2D(latitude: newLatitude, longitude: newLongitude)
}

Then the above code would simply look like this:

let coordinate = CLLocationCoordinate2D(latitude: 9.0, longitude: 50.0)
let distance: CLLocationDistance = 5000 // 5km
let topLeftCoordinate = self.coordinate(from: coordinate, distance: -distance)
let bottomRightCoordinate = self.coordinate(from: coordinate, distance: distance)

Hope it helps someone out there when coming across this.


Precautious Info: Just in case someone thinks (as many seem to do) that a self-answered question isn't appropriate on SO, please read this first.

Calculate Coord from start point, endpoint, and distance

Thanks to @HansKilian and @cletus (Calculate distance between 2 GPS coordinates), I could find the solution

private const double EARTH_RADIUS = 6378.1;
private static double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}
private static double ConvertToDegree(double angle)
{
return angle * (180.0 / Math.PI);
}

private static double CalculateBearing(CoordsDto from, CoordsDto to)
{
var from_lat_rad = ConvertToRadians(from.Latitud);
var to_lat_rad = ConvertToRadians(to.Latitud);

var dif_lng_rad = ConvertToRadians(to.Longitud - from.Longitud);

double x = Math.Cos(from_lat_rad) * Math.Sin(to_lat_rad) - Math.Sin(from_lat_rad) * Math.Cos(to_lat_rad) * Math.Cos(dif_lng_rad);
double y = Math.Sin(dif_lng_rad) * Math.Cos(to_lat_rad);

// Math.Atan2 can return negative value, 0 <= output value < 2*PI expected
return (Math.Atan2(y, x) + Math.PI * 2) % (Math.PI * 2);
}

public static CoordsDto GetPointFarAway(CoordsDto from, CoordsDto to, double meterAwayFromStart)
{
var resp = new CoordsDto();
var bearing_rad = CalculateBearing(from, to);
var d = meterAwayFromStart * 0.001; //KM

var input_lat1_rad = ConvertToRadians(from.Latitud);
var input_lon1_rad = ConvertToRadians(from.Longitud);

var newPoint_lat_rad = Math.Asin(
Math.Sin(input_lat1_rad) * Math.Cos(d / EARTH_RADIUS) + Math.Cos(input_lat1_rad) * Math.Sin(d / EARTH_RADIUS) * Math.Cos(bearing_rad)
);
var newPoint_lon_rad = input_lon1_rad + Math.Atan2(
Math.Sin(bearing_rad) * Math.Sin(d / EARTH_RADIUS) * Math.Cos(input_lat1_rad),
Math.Cos(d / EARTH_RADIUS) - Math.Sin(input_lat1_rad) * Math.Sin(newPoint_lat_rad)
);

resp.Latitud = ConvertToDegree(newPoint_lat_rad);
resp.Longitud = ConvertToDegree(newPoint_lon_rad);

return resp;
}

Create coordinate based on distance and direction

You can use formula from this excellent site (section Destination point given distance and bearing from start point)

var φ2 = Math.asin( Math.sin(φ1)*Math.cos(d/R) +
Math.cos(φ1)*Math.sin(d/R)*Math.cos(brng) );
var λ2 = λ1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(φ1),
Math.cos(d/R)-Math.sin(φ1)*Math.sin(φ2));

where φ is latitude, λ is longitude, θ is the bearing (clockwise from north), δ is the angular distance d/R; d being the distance travelled, R the earth’s radius

Calculate coordinate by distance from another coordinate

    CLLocation Point1;
CLLocation Point2;
float targetDistance;

float length = sqrt((Point1.x-Point2.x)*(Point1.x-Point2.x) + (Point1.y-Point2.y)*(Point1.y-Point2.y));

CLLocation result;
result.x = Point1.x + (Point2.x-Point1.x)*(targetDistance/length);
result.y = Point1.y + (Point2.y-Point1.y)*(targetDistance/length);

Or in other words Point1 + normalized(Point2-Point1)*targetDistance

Since you have an angle you could also do:

Point1 + (cos(angle)*targetDistance, sin(angle)*targetDistance)

Find destination coordinates given starting coordinates, bearing, and distance

According to this page

math.sin(x) ... Return the sine of x radians.

So, you need to convert lat1 and lon1 to radians before your equation and then later you can convert lat2 and lon2 back into degrees.



Related Topics



Leave a reply



Submit