I'm trying to generate some points at random distances away from a fixed point using GPS.
How can I add distance in meters to a GPS coordinate?
I've looked at UTM to GPS conversion but is there a simpler method to achieve this?
I'm working on Android platform just in case.
Cheers,
fgs
P0(lat0,lon0) : initial position (unit : degrees)
dx,dy : random offsets from your initial position in meters
You can use an approximation to compute the position of the randomized position:
lat = lat0 + (180/pi)*(dy/6378137)
lon = lon0 + (180/pi)*(dx/6378137)/cos(lat0)
This is quite precise as long as the random distance offset is below 10-100 km
Edit: of course in Java Math.cos() expects radians so do use Math.cos(Math.PI/180.0*lat0) if lat0 is in degrees as assumed above.
To take a square I'm using this:
private double[] getBoundingBox(final double pLatitude, final double pLongitude, final int pDistanceInMeters) {
final double[] boundingBox = new double[4];
final double latRadian = Math.toRadians(pLatitude);
final double degLatKm = 110.574235;
final double degLongKm = 110.572833 * Math.cos(latRadian);
final double deltaLat = pDistanceInMeters / 1000.0 / degLatKm;
final double deltaLong = pDistanceInMeters / 1000.0 / degLongKm;
final double minLat = pLatitude - deltaLat;
final double minLong = pLongitude - deltaLong;
final double maxLat = pLatitude + deltaLat;
final double maxLong = pLongitude + deltaLong;
boundingBox[0] = minLat;
boundingBox[1] = minLong;
boundingBox[2] = maxLat;
boundingBox[3] = maxLong;
return boundingBox;
}
This returns an array with 4 coordinates, with them you can make a square with your original point in center.
A detailed outline is given at http://www.movable-type.co.uk/scripts/latlong.html.
If you, somewhere, need to interconvert longitude/latitude to UTM coordinates (the ones used in GPS) you may want to have a look at http://www.uwgb.edu/dutchs/UsefulData/UTMFormulas.htm
If you want to go east or north or west or south you can use this:
#SuppressLint("DefaultLocale")
public static double go_mock_loc(double xx_lat,double xx_long,double xx_dinstance,String Direction)
{
// double xx_lat= 45.815005;
// double xx_long= 15.978501;
// int xx_dinstance=500;
int equator_circumference=6371000;
int polar_circumference=6356800;
double m_per_deg_long = 360 / polar_circumference;
double rad_lat=(xx_lat* (Math.PI) / 180);
double m_per_deg_lat = 360 / ( Math.cos(rad_lat) * equator_circumference);
double deg_diff_long = xx_dinstance * m_per_deg_long;
double deg_diff_lat = xx_dinstance * m_per_deg_lat;
double xx_north_lat = xx_lat + deg_diff_long;
//double xx_north_long= xx_long;
double xx_south_lat = xx_lat - deg_diff_long;
//double xx_south_long= xx_long;
//double xx_east_lat = xx_lat;
double xx_east_long= xx_long + deg_diff_lat;
//double xx_west_lat = xx_lat;
double xx_west_long= xx_long - deg_diff_lat;
if (Direction.toUpperCase().contains("NORTH")) {
return xx_north_lat;
} else if (Direction.toUpperCase().contains("SOUTH"))
{
return xx_south_lat;
} else if (Direction.toUpperCase().contains("EAST"))
{
return xx_east_long;
} else if (Direction.toUpperCase().contains("WEST"))
{
return xx_west_long;
}
else
return 0;
}
I found that solution of #Bogdan Khrystov is very well.
So here is C# version of his solution.
public enum GeoDirection
{
NORTH = 1, SOUTH = 2, EAST = 3, WEST = 4
}
public static Tuple<double, double> AddDistanceInMeters(double latitude, double longitude, int distanceInMeters, GeoDirection direction)
{
var equatorCircumference = 6371000;
var polarCircumference = 6356800;
var mPerDegLong = 360 / (double)polarCircumference;
var radLat = latitude * Math.PI / 180;
var mPerDegLat = 360 / (Math.Cos(radLat) * equatorCircumference);
var degDiffLong = distanceInMeters * mPerDegLong;
var degDiffLat = distanceInMeters * mPerDegLat;
var xxNorthLat = latitude + degDiffLong;
var xxSouthLat = latitude - degDiffLong;
var xxEastLong = longitude + degDiffLat;
var xxWestLong = longitude - degDiffLat;
switch (direction)
{
case GeoDirection.NORTH:
return new Tuple<double, double>(xxNorthLat, longitude);
case GeoDirection.SOUTH:
return new Tuple<double, double>(xxSouthLat, longitude);
case GeoDirection.EAST:
return new Tuple<double, double>(latitude, xxEastLong);
case GeoDirection.WEST:
return new Tuple<double, double>(latitude, xxWestLong);
default:
return null;
}
}
rewrite #Ersin Gülbahar answer in Kotlin:
object LocationUtil {
enum class Direction {
NORTH, SOUTH, EAST, WEST
}
fun addDistanceInMeters(
latitude: Double,
longitude: Double,
distanceInMeters: Int,
direction: Direction
): Pair<Double, Double> {
val equatorCircumference = 6371000
val polarCircumference = 6356800
val mPerDegLong = (360 / polarCircumference.toDouble())
val radLat = latitude * Math.PI / 180
val mPerDegLat = 360 / (Math.cos(radLat) * equatorCircumference)
val degDiffLong = distanceInMeters * mPerDegLong
val degDiffLat = distanceInMeters * mPerDegLat
val xxNorthLat = latitude + degDiffLong
val xxSouthLat = latitude - degDiffLong
val xxEastLong = longitude + degDiffLat
val xxWestLong = longitude - degDiffLat
return when (direction) {
Direction.NORTH -> Pair(xxNorthLat, longitude)
Direction.SOUTH -> Pair(xxSouthLat, longitude)
Direction.EAST -> Pair(latitude, xxEastLong)
Direction.WEST -> Pair(latitude, xxWestLong)
}
}
}
This code splits the line between two coordinates in n segments. Replace the delta calculation by your fixed distance
#Override
public void split(Coordinates p1, Coordinates p2, int segments) {
double φ1 = Math.toRadians(p1.getLat());
double λ1 = Math.toRadians(p1.getLon());
double φ2 = Math.toRadians(p2.getLat());
double λ2 = Math.toRadians(p2.getLon());
double xDelta = (φ2 - φ1) / segments;
double yDelta = (λ2 - λ1) / segments;
for (int i = 0; i < segments; i++){
double x = φ1 + i * xDelta;
double y = λ1 + i * yDelta;
double xc = Math.toDegrees(x);
double yc = Math.toDegrees(y);
System.out.println(xc+","+yc);
}
}
Combining answers from #Ersin Gülbahar and #Stéphane above, I came up with this solution in Flutter/Dart:
import 'dart:math' as math;
enum Direction { north, south, east, west }
double moveCoordinate(
double latitude, double longitude, double distanceToMoveInMeters, Direction directionToMove) {
const earthEquatorRadius = 6378137;
final latitudeOffset = (180 / math.pi) * (distanceToMoveInMeters / earthEquatorRadius);
final longitudeOffset = (180 / math.pi) *
(distanceToMoveInMeters / earthEquatorRadius) /
math.cos(math.pi / 180 * latitude);
switch (directionToMove) {
case Direction.north:
return latitude + latitudeOffset;
case Direction.south:
return latitude - latitudeOffset;
case Direction.east:
return longitude + longitudeOffset;
case Direction.west:
return longitude - longitudeOffset;
}
return 0;
}
This works, tested. The code is C# but you can easily change it to another language
private PointLatLng NewPositionBasedOnDistanceAngle(PointLatLng org, double distance, double bearing)
{
double rad = bearing * Math.PI / 180; //to radians
double lat1 = org.Lat * Math.PI / 180; //to radians
double lng1 = org.Lng * Math.PI / 180; //to radians
double lat = Math.Asin(Math.Sin(lat1) * Math.Cos(distance / 6378137) + Math.Cos(lat1) * Math.Sin(distance / 6378137) * Math.Cos(rad));
double lng = lng1 + Math.Atan2(Math.Sin(rad) * Math.Sin(distance / 6378137) * Math.Cos(lat1), Math.Cos(distance / 6378137) - Math.Sin(lat1) * Math.Sin(lat));
return new PointLatLng(lat * 180 / Math.PI, lng * 180 / Math.PI); // to degrees
}
Related
I have two geo positions lets say A and B and distance between both of them say D.
So I know A, B, and D.
Now I want to get all the points (l,m,n,o... etc.) in a distance of 3 meters each.
Note:
If I draw a straight line between A and B then all the required points should lie on that straight line.
What I have done so far:
I have searched a lot and come across this website but there is an example which is in javascript and when I converted this code into c# then I do not get exact points.
Please help me! Thank you!
For those who believe this question as a duplicate for like this then I want to clarify that I do not need to calculate distance. In my question distance is already known.
Finally, I came across the following Code:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
namespace Calc
{
public static class Program
{
private static readonly long RADIUS_OF_EARTH = 6371000; // radius of earth in m
public static void Main(string[] args)
{
// point interval in meters
int interval =2;
// direction of line in degrees
//start point
double lat1 = 28.6514975008004;
double lng1 = 77.2216437757015;
// end point
double lat2 = 28.6514763167883;
double lng2 = 77.2221480309963;
MockLocation start = new MockLocation(lat1, lng1);
MockLocation end = new MockLocation(lat2, lng2);
double azimuth = calculateBearing(start, end);
Console.WriteLine(azimuth);
List<MockLocation> coords = getLocations(interval, azimuth, start, end);
foreach (MockLocation mockLocation in coords)
{
Console.WriteLine(mockLocation.lat + ", " + mockLocation.lng);
}
Console.ReadLine();
}
/**
* returns every coordinate pair in between two coordinate pairs given the desired interval
* #param interval
* #param azimuth
* #param start
* #param end
* #return
*/
private static List<MockLocation> getLocations(int interval, double azimuth, MockLocation start, MockLocation end)
{
Console.WriteLine("getLocations: " +
"\ninterval: " + interval +
"\n azimuth: " + azimuth +
"\n start: " + start.toString());
double d = getPathLength(start, end);
int dist = (int)d / interval;
int coveredDist = interval;
List<MockLocation> coords = new List<MockLocation>();
MockLocation mock = new MockLocation(start.lat, start.lng);
coords.Add(mock);
for (int distance = 0; distance < dist; distance += interval)
{
MockLocation coord = getDestinationLatLng(start.lat, start.lng, azimuth, coveredDist);
coveredDist += interval;
coords.Add(coord);
}
coords.Add(new MockLocation(end.lat, end.lng));
return coords;
}
public static double ToRadians(this double val)
{
return (Math.PI / 180) * val;
}
/**
* calculates the distance between two lat, long coordinate pairs
* #param start
* #param end
* #return
*/
private static double getPathLength(MockLocation start, MockLocation end)
{
double lat1Rads = ToRadians(start.lat);
double lat2Rads = ToRadians(end.lat);
double deltaLat = ToRadians(end.lat - start.lat);
double deltaLng = ToRadians(end.lng - start.lng);
double a = Math.Sin(deltaLat / 2) * Math.Sin(deltaLat / 2) + Math.Cos(lat1Rads) * Math.Cos(lat2Rads) * Math.Sin(deltaLng / 2) * Math.Sin(deltaLng / 2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
double d = RADIUS_OF_EARTH * c;
return d;
}
/**
* returns the lat an long of destination point given the start lat, long, aziuth, and distance
* #param lat
* #param lng
* #param azimuth
* #param distance
* #return
*/
private static MockLocation getDestinationLatLng(double lat, double lng, double azimuth, double distance)
{
double radiusKm = RADIUS_OF_EARTH / 1000; //Radius of the Earth in km
double brng = ToRadians(azimuth); //Bearing is degrees converted to radians.
double d = distance / 1000; //Distance m converted to km
double lat1 = ToRadians(lat); //Current dd lat point converted to radians
double lon1 = ToRadians(lng); //Current dd long point converted to radians
double lat2 = Math.Asin(Math.Sin(lat1) * Math.Cos(d / radiusKm) + Math.Cos(lat1) * Math.Sin(d / radiusKm) * Math.Cos(brng));
double lon2 = lon1 + Math.Atan2(Math.Sin(brng) * Math.Sin(d / radiusKm) * Math.Cos(lat1), Math.Cos(d / radiusKm) - Math.Sin(lat1) * Math.Sin(lat2));
//convert back to degrees
lat2 = ToDegrees(lat2);
lon2 = ToDegrees(lon2);
return new MockLocation(lat2, lon2);
}
/**
* calculates the azimuth in degrees from start point to end point");
double startLat = ToRadians(start.lat);
* #param start
* #param end
* #return
*/
private static double calculateBearing(MockLocation start, MockLocation end)
{
double startLat = ToRadians(start.lat);
double startLong = ToRadians(start.lng);
double endLat = ToRadians(end.lat);
double endLong = ToRadians(end.lng);
double dLong = endLong - startLong;
double dPhi = Math.Log(Math.Tan((endLat / 2.0) + (Math.PI / 4.0)) / Math.Tan((startLat / 2.0) + (Math.PI / 4.0)));
if (Math.Abs(dLong) > Math.PI)
{
if (dLong > 0.0)
{
dLong = -(2.0 * Math.PI - dLong);
}
else
{
dLong = (2.0 * Math.PI + dLong);
}
}
double bearing = (ToDegrees(Math.Atan2(dLong, dPhi)) + 360.0) % 360.0;
return bearing;
}
public static double ToDegrees(double radians)
{
double degrees = (180 / Math.PI) * radians;
return (degrees);
}
public class MockLocation
{
public double lat;
public double lng;
public MockLocation(double lat, double lng)
{
this.lat = lat;
this.lng = lng;
}
public string toString()
{
return (lat + "," + lng).ToString();
}
}
}
}
I hope this will help other learners.
I have two geo coordinates (Start and End Points) and I am able to create a line between them. Suppose these two coordinates are at a distance of 30 meters then I need to find every geolocation of points at an interval of 3 meters. So there are 10 such points which are required.
I am able to find the points by some formulas but these points are not in the same direction as the line formed by start and end points.
What I have done so far is below...
using System;
namespace Test
{
public class AzimuthCalculator
{
public const double range = 0.00186411F; // in Miles
public const double rangeInMeter = 3F;
public const double factor = 0.003F;
public static void Main(String[] args)
{
double sLatitude = 28.6187763214111F;
double sLongitude = 77.2093048095703F;
double eLatitude = 28.6191763153134F;
double eLongitude = 77.2097146511078F;
Console.WriteLine($"Start Point : {sLatitude}, {sLongitude}");
Console.WriteLine($"End Point : {eLatitude},{eLongitude}");
double distance = CalculateDistance(sLatitude, sLongitude, eLatitude, eLongitude);
Console.WriteLine($"Distance : {distance} miles, {MilesToMeter(distance)} meter, {(distance * 1.60934)} kilometer");
distance = distance * 1.60934;
double numberOfIDS = distance/factor;
double azimuthAngle = DegreeBearing(sLatitude, sLongitude, eLatitude, eLongitude);
Console.WriteLine($"Azimuth : {azimuthAngle}");
Console.WriteLine($"IDS : {numberOfIDS}");
double constantAzimuth = (azimuthAngle/numberOfIDS);
azimuthAngle = constantAzimuth;
Console.WriteLine($"Original Azimuth : {azimuthAngle}");
double[] getAnotherPoint = pointRadialDistance(sLatitude, sLongitude, azimuthAngle, distance);
Console.WriteLine($"End Point : {getAnotherPoint[0]},{getAnotherPoint[1]}");
distance = 0.003; // 3 meter
getAnotherPoint = pointRadialDistance(sLatitude, sLongitude, azimuthAngle, distance);
int totalIDS = (Int32)(numberOfIDS);
for(int i=0;i<totalIDS;i++)
{
sLatitude = getAnotherPoint[0];
sLongitude = getAnotherPoint[1];
distance = 0.003;
Console.WriteLine($"new PointLatLng({getAnotherPoint[0]},{getAnotherPoint[1]}),");
getAnotherPoint = pointRadialDistance(sLatitude, sLongitude, azimuthAngle, distance);
}
Console.ReadLine();
}
static double rEarth = 6371.01F; // Earth radius in km
static double epsilon = 0.000001F;
public static double[] pointRadialDistance(double lat1, double lon1, double bearing, double distance)
{
double rlat1 = ToRad(lat1);
double rlon1 = ToRad(lon1);
double rbearing = ToRad(bearing);
double rdistance = distance / rEarth; // normalize linear distance to radian angle
double rlat = Math.Asin( Math.Sin(rlat1) * Math.Cos(rdistance) + Math.Cos(rlat1) * Math.Sin(rdistance) * Math.Cos(rbearing));
double rlon = 0.0F;
if ( Math.Cos(rlat) == 0 || Math.Abs(Math.Cos(rlat)) < epsilon) // Endpoint a pole
rlon=rlon1;
else
rlon = ((rlon1 - Math.Asin( Math.Sin(rbearing) * Math.Sin(rdistance) / Math.Cos(rlat) ) + Math.PI ) % (2*Math.PI) ) - Math.PI;
double lat = ToDegrees(rlat);
double lon = ToDegrees(rlon);
double[] listNew = new double[2];
listNew[0] = lat;
listNew[1] = lon;
return (listNew);
}
public static GeoLocation FindPointAtDistanceFrom(GeoLocation startPoint, double initialBearingRadians, double distanceKilometres)
{
const double radiusEarthKilometres = 6371.01;
var distRatio = distanceKilometres / radiusEarthKilometres;
var distRatioSine = Math.Sin(distRatio);
var distRatioCosine = Math.Cos(distRatio);
var startLatRad = DegreesToRadians(startPoint.Latitude);
var startLonRad = DegreesToRadians(startPoint.Longitude);
var startLatCos = Math.Cos(startLatRad);
var startLatSin = Math.Sin(startLatRad);
var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));
var endLonRads = startLonRad
+ Math.Atan2(
Math.Sin(initialBearingRadians) * distRatioSine * startLatCos,
distRatioCosine - startLatSin * Math.Sin(endLatRads));
return new GeoLocation
{
Latitude = RadiansToDegrees(endLatRads),
Longitude = RadiansToDegrees(endLonRads)
};
}
public struct GeoLocation
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public static double DegreesToRadians(double degrees)
{
const double degToRadFactor = Math.PI / 180;
return degrees * degToRadFactor;
}
public static double RadiansToDegrees(double radians)
{
const double radToDegFactor = 180 / Math.PI;
return radians * radToDegFactor;
}
public static double CalculateDistance(double sLatitude, double sLongitude, double eLatitude, double eLongitude)
{
var radiansOverDegrees = (Math.PI / 180.0);
var sLatitudeRadians = sLatitude * radiansOverDegrees;
var sLongitudeRadians = sLongitude * radiansOverDegrees;
var eLatitudeRadians = eLatitude * radiansOverDegrees;
var eLongitudeRadians = eLongitude * radiansOverDegrees;
var dLongitude = eLongitudeRadians - sLongitudeRadians;
var dLatitude = eLatitudeRadians - sLatitudeRadians;
var result1 = Math.Pow(Math.Sin(dLatitude / 2.0), 2.0) + Math.Cos(sLatitudeRadians) * Math.Cos(eLatitudeRadians) * Math.Pow(Math.Sin(dLongitude / 2.0), 2.0);
// Using 3956 as the number of miles around the earth
var result2 = 3956.0 * 2.0 * Math.Atan2(Math.Sqrt(result1), Math.Sqrt(1.0 - result1));
return result2;
}
static double DegreeBearing(double lat1, double lon1,double lat2, double lon2)
{
var dLon = ToRad(lon2 - lon1);
var dPhi = Math.Log(Math.Tan(ToRad(lat2) / 2 + Math.PI / 4) / Math.Tan(ToRad(lat1) / 2 + Math.PI / 4));
if (Math.Abs(dLon) > Math.PI)
dLon = dLon > 0 ? - (2 * Math.PI - dLon) : (2 * Math.PI + dLon);
return ToBearing(Math.Atan2(dLon, dPhi));
}
public static double ToRad(double degrees)
{
return degrees * (Math.PI / 180);
}
public static double ToDegrees(double radians)
{
return radians * 180 / Math.PI;
}
public static double ToBearing(double radians)
{
// convert radians to degrees (as bearing: 0...360)
return (ToDegrees(radians) + 360) % 360;
}
public static double MeterToMiles(double meter)
{
return (meter / 1609.344);
}
public static double MilesToMeter(double miles)
{
return (miles * 1609.344);
}
}
}
Why do you calculate wrong bearing from right one here constantAzimuth = (azimuthAngle/numberOfIDS); and use it later?
You can calculate intermediate points on the great circle path using approach described here (essentially it is SLERP - spherical linear interpolation)
Formula:
a = sin((1−f)⋅δ) / sin δ
b = sin(f⋅δ) / sin δ
x = a ⋅ cos φ1 ⋅ cos λ1 + b ⋅ cos φ2 ⋅ cos λ2
y = a ⋅ cos φ1 ⋅ sin λ1 + b ⋅ cos φ2 ⋅ sin λ2
z = a ⋅ sin φ1 + b ⋅ sin φ2
φi = atan2(z, √x² + y²)
λi = atan2(y, x)
where
f is fraction along great circle route (f=0 is point 1, f=1 is point 2),
δ is the angular distance d/R between the two points.
I am using a solution I've found in this post:
Polygon area calculation using Latitude and Longitude generated from Cartesian space and a world file
There is something wrong because the values I am getting are not real. For example we know a football field should have around 5,300.00 square meters, right? but the calculation is giving 5,759,154.21.
This is the code:
private static double CalculatePolygonArea(IList<Position> coordinates)
{
double area = 0;
if (coordinates.Count > 2)
{
for (var i = 0; i < coordinates.Count - 1; i++)
{
Position p1 = coordinates[i];
Position p2 = coordinates[i + 1];
area += (ConvertToRadian(p2.Longitude) - ConvertToRadian(p1.Longitude)) * (2 + Math.Sin(ConvertToRadian(p1.Latitude)) + Math.Sin(ConvertToRadian(p2.Latitude)));
}
area = area * 6378137 * 6378137 / 2;
}
return Math.Abs(area);
}
private static double ConvertToRadian(double input)
{
return input * Math.PI / 180;
}
What can be wrong here? Any help?
The area calculation you are using is just plain wrong.... :-/
I use the SphericalUtil.ComputeSignedArea method from Google's Android Maps Utils.
Note: Google's Java code for that is under Apache License Version 2.0, and I converted it to C#.
Looking up that football field up in one of my apps, I get: 4,461, not quite the actual 5,531 but not bad for using Google Map photos...
Here is just the ComputeSignedArea:
public static class SphericalUtil
{
const double EARTH_RADIUS = 6371009;
static double ToRadians(double input)
{
return input / 180.0 * Math.PI;
}
public static double ComputeSignedArea(IList<LatLng> path)
{
return ComputeSignedArea(path, EARTH_RADIUS);
}
static double ComputeSignedArea(IList<LatLng> path, double radius)
{
int size = path.Count;
if (size < 3) { return 0; }
double total = 0;
var prev = path[size - 1];
double prevTanLat = Math.Tan((Math.PI / 2 - ToRadians(prev.Latitude)) / 2);
double prevLng = ToRadians(prev.Longitude);
foreach (var point in path)
{
double tanLat = Math.Tan((Math.PI / 2 - ToRadians(point.Latitude)) / 2);
double lng = ToRadians(point.Longitude);
total += PolarTriangleArea(tanLat, lng, prevTanLat, prevLng);
prevTanLat = tanLat;
prevLng = lng;
}
return total * (radius * radius);
}
static double PolarTriangleArea(double tan1, double lng1, double tan2, double lng2)
{
double deltaLng = lng1 - lng2;
double t = tan1 * tan2;
return 2 * Math.Atan2(t * Math.Sin(deltaLng), 1 + t * Math.Cos(deltaLng));
}
}
I am working on getting data out of the Noaa API.
When talking to the Noaa API you can get a list of weather stations within a square. They call them "extents" and they are a 2 sets of lat/longs. The bottom left lat/long and the top right lat/long
As detailed here:
http://www.ncdc.noaa.gov/cdo-web/webservices/v2#stations
I have been given a list of lat/longs for a number of cities in the US and I am trying to work out the best way of putting a box around.
So, my first guess would be to take the central lat/long, work out the lat/long 75 miles to the West, then work out the lat/long of the point 75 miles South of that point.
Ideally I would like to have this as a c# function.
Has anyone got any ideas on the best way to code this please?
Thanks
Yippee! - found the solution...
First a simple class:
public class LatLonAlt
{
public double Latitude { get; set; }
public double Longitude { get; set; }
public double Altitude { get; set; }
}
Then a function to calculate a new position:
public static HelpersModel.LatLonAlt CalculateDerivedPosition(HelpersModel.LatLonAlt source, double range, double bearing)
{
double latA = Convert.ToDouble(source.Latitude) * (Math.PI / 180);
double lonA = Convert.ToDouble(source.Longitude) * (Math.PI / 180);
double angularDistance = range / 6371;
double trueCourse = bearing * (Math.PI / 180);
double lat = Math.Asin(
Math.Sin(latA) * Math.Cos(angularDistance) +
Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));
double dlon = Math.Atan2(
Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));
double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;
HelpersModel.LatLonAlt results = new HelpersModel.LatLonAlt();
results.Latitude = lat * (180 / Math.PI);
results.Longitude = lon * (180 / Math.PI);
results.Altitude = source.Altitude;
return results;
}
Then, and I know I can do this better.. but it works for now...
2 functions that work out the bottmleft and topright extent:
public static HelpersModel.LatLonAlt FindBottomLeftExtent(HelpersModel.LatLonAlt startpoint)
{
// first move left
HelpersModel.LatLonAlt movedleft = CalculateDerivedPosition(startpoint, 72.42, 270);
// move down
HelpersModel.LatLonAlt moveddown = CalculateDerivedPosition(movedleft, 72.42, 180);
return moveddown;
}
public static HelpersModel.LatLonAlt FindTopRightExtent(HelpersModel.LatLonAlt startpoint)
{
// first move right
HelpersModel.LatLonAlt movedright = CalculateDerivedPosition(startpoint, 72.42, 90);
// move up
HelpersModel.LatLonAlt movedup = CalculateDerivedPosition(movedright, 72.42, 0);
return movedup;
}
HTH!
Trev
I am trying to sort out a method to calculate the distance between 2 points in c#.
This is the code I have been trying though I fear the answer I get is not correct.
static void Main()
{
//postcode australia 2600 -> 3000
float latA = -31.997976f;
float longA = 115.762877f;
float latB = -31.99212f;
float longB = 115.763228f;
decimal distance = (DistanceBetween(latA, latB, longA, longB));
Console.WriteLine("Distance is" + distance);
Console.ReadLine();
}
static decimal DistanceBetween(float latA, float longA, float latB, float longB)
{
var RadianLatA = Math.PI * latA / 180;
var RadianLatb = Math.PI * latB / 180;
var RadianLongA = Math.PI * longA / 180;
var RadianLongB = Math.PI * longB / 180;
double theDistance = (Math.Sin(RadianLatA)) *
Math.Sin(RadianLatb) +
Math.Cos(RadianLatA) *
Math.Cos(RadianLatb) *
Math.Cos(RadianLongA - RadianLongB);
return Convert.ToDecimal(((Math.Acos(theDistance) * (180.0 / Math.PI)))) * 69.09M * 1.6093M;
}
this was adapted from a response found on this site here
Distance between addresses
Any thoughts on what is going wrong/
Thanks
Ryan
The class I usually use is GeoCoordinate
double latA = -31.997976f;
double longA = 115.762877f;
double latB = -31.99212f;
double longB = 115.763228f;
var locA = new GeoCoordinate(latA, longA);
var locB = new GeoCoordinate(latB, longB);
double distance = locA.GetDistanceTo(locB ); // metres
double lat1 = {};
double lat2 = {};
double lon1 = {};
double lon2 = {};
var R = 6376.5000; //Km
lat1 = lat1.ToRad();
lat2 = lat2.ToRad();
lon1 = lon1.ToRad();
lon2 = lon2.ToRad();
var dLat = lat2 - lat1;
var dLon = lon2 - lon1;
var a = Math.Pow(Math.Sin(dLat / 2), 2) + (Math.Pow(Math.Sin(dLon / 2), 2) * Math.Cos(lat1) * Math.Cos(lat2));
var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
var distance = R * c;
public double ToRad(this double degs) {
return degs * (Math.PI/180.0);
}
Input expects doubles.
This is the haversine formula, it's used to calculate the distances on our globe between two points. This is the distance in a straight line, if you need the distance on a path you will have to find all points on that path and then calculate the distances between each two points and then take the sum of that.
You can use DbGeography for spatial calculation. It has DbGeography.Distance method which is used to calculate the distance between two gps points.
Otherwise, try Ref: Harversine Formula to calculate the distance between two points.
Distance Formula: Given the two points (x1, y1) and (x2, y2), the distance between these points is given by the formula:
use it accordingly