Xamarin.Forms - Get miles Between Two Coordinates Using Xamarin.Essentials - c#

I am trying to get the miles between to locations using xamarin essentials. I a have the coordinates for the staring point and destination. The Distance variable equals to 2134.13057845059. Do I need to convert this number to miles? It should equal to 30 miles or so.
var location = await Geolocation.GetLastKnownLocationAsync();
var courtLocation = new Location(Convert.ToDouble(item.Latitude), Convert.ToDouble(item.Longitude));
double distance = Location.CalculateDistance(location, courtLocation, DistanceUnits.Miles);

the last parameter of CalculateDistance is the unit for the return type.
you are requesting km
double distance = Location.CalculateDistance(location, courtLocation, DistanceUnits.Kilometers);
if you want to request miles, use
double distance = Location.CalculateDistance(location, courtLocation, DistanceUnits.Miles);
this works for me, if you are still getting a bad result I would double check your inputs and conversions
var loc1 = new Location(33.887749, -84.345818);
var loc2 = new Location(33.807920, -84.046791);
// result is 18.023...
double distance = Location.CalculateDistance(loc1, loc2, DistanceUnits.Miles);

Related

Latitude and Longitude to pixel-value in GDAL

I'm trying to read a GeoTIFF with one band which stores a value between 0 and 3 ( 255 is no maks ). My Goal is to write a little program which takes in a latitude/longitude and returns the fitting pixel value at the geocoordinate in the geotiff.
I downloaded it from here : https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/QQHCIK
And if you wanna take a look at it... heres the download link. https://drive.google.com/file/d/104De_YQN1V8tSbj2uhIPO0FfowjnInnX/view?usp=sharing
However, my code does not work. I cant tell you what is wrong, it just outputs the wrong pixel value every damn time. I guess either my geocordinate to pixel transformation is wrong or theres a huge logic mistake.
This was my first try, it prints the wrong value for the geo-coordinate.
Furthermore it crashes with some geocoordinates, a negative longitude makes it crashes because this will make pixelY negative which causes an exception in the raster method.
GdalConfiguration.ConfigureGdal();
var tif = "C:\\Users\\Lars\\Downloads\\pnv_biome.type_biome00k_c_1km_s0..0cm_2000..2017_v0.1.tif";
var lat = 51.0;
var lon = 8.3;
using (var image = Gdal.Open(tif, Access.GA_ReadOnly)) {
var bOneBand = image.GetRasterBand(1);
var width = bOneBand.XSize;
var height = bOneBand.YSize;
// Geocoordinate ( lat, lon ) to pixel in the tiff ?
var geoTransform = new double[6];
image.GetGeoTransform(geoTransform);
Gdal.InvGeoTransform(geoTransform, geoTransform);
var bOne = new int[1];
Gdal.ApplyGeoTransform(geoTransform, lat, lon, out var pixelXF, out var pixelYF);
var pixelX = (int)Math.Floor(pixelXF);
var pixelY = (int)Math.Floor(pixelYF);
// Read pixel
bOneBand.ReadRaster(pixelX, pixelY, 1, 1, bOne, 1, 1,0,0);
Console.WriteLine(bOne[0]); // bOne[0] contains wrong data
}
My second attempt looks like the following... but also outputs the wrong pixel value for the given coordinates. It also crashes with some geocoordinates.
GdalConfiguration.ConfigureGdal();
var tif = "C:\\Users\\Lars\\Downloads\\pnv_biome.type_biome00k_c_1km_s0..0cm_2000..2017_v0.1.tif";
var lat = 24.7377; // 131.5847
var lon = 131.5847;
using (var image = Gdal.Open(tif, Access.GA_ReadOnly)) {
var bOneBand = image.GetRasterBand(1);
var bOne = new int[1];
// Spatial reference to transform latlng to map coordinates... from python code
var point_srs = new SpatialReference("");
var file_srs = new SpatialReference(image.GetProjection());
point_srs.ImportFromEPSG(4326);
point_srs.SetAxisMappingStrategy(AxisMappingStrategy.OAMS_TRADITIONAL_GIS_ORDER);
var mapCoordinates = new double[2]{ lat, lon};
var transform = new CoordinateTransformation(point_srs, file_srs);
transform.TransformPoint(mapCoordinates);
// Map coordinates to pixel coordinates ?
var geoTransform = new double[6];
image.GetGeoTransform(geoTransform);
Gdal.InvGeoTransform(geoTransform, geoTransform);
Gdal.ApplyGeoTransform(geoTransform, mapCoordinates[0], mapCoordinates[1], out var pixelXF, out var pixelYF);
var pixelX = (int)pixelXF;
var pixelY = (int)pixelYF;
bOneBand.ReadRaster(pixelX, pixelY, 1, 1, bOne, 1, 1, 0,0);
Console.WriteLine(bOne[0]); // bOne[0] contains wrong value
}
What is wrong with my code, why does it output the wrong pixel value ?
Any help appreciated !
Perhaps you are using lat/lon where it should be lon/lat? It would be helpful if you printed some values such as mapCoordinates.
Here is how you can do this with R, for comparison:
library(terra)
r = rast("pnv_biome.type_biome00k_c_1km_s0..0cm_2000..2017_v0.1.tif")
xy = cbind(c(8.3, 131.5847), c(51.0, 24.7377))
extract(r, xy)
# pnv_biome.type_biome00k_c_1km_s0..0cm_2000..2017_v0.1
#1 9
#2 NA
And the zero-based row/col numbers
rowColFromCell(r, cellFromXY(r, xy)) - 1
# [,1] [,2]
#[1,] 4364 22596
#[2,] 7515 37390
And you can use describe (a.k.a. GDALinfo) to get some metadata. E.g.
d = describe("pnv_biome.type_biome00k_c_1km_s0..0cm_2000..2017_v0.1.tif")
d[50]
# [1] "Band 1 Block=43200x1 Type=Byte, ColorInterp=Gray"

GPS lap & Segment timer

I've been searching for a while but haven't found exactly what I'm looking for.
I'm working on an app that will go in a race car. It will give the driver the ability to press a button to mark a Start/Finish line. It will also have a button to allow a driver to set segment times.
Keep in mind a track can be an oval which I'm working on first. It could be a road course or it could be an auto cross where the start and finish line aren't the exact same location. They could be with 50 feet of each other or so but the car never crosses where it starts.
I have my gps data coming in and I convert the NMea messages to my classes and I store Lat, Lon, Speed, Course etc. In my research I've ran across this which is interesting. The GPS will be mounted outside the roof for better signal. It generates 10 hits per second. (Garmin Glo)
http://www.drdobbs.com/windows/gps-programming-net/184405690?pgno=1
It's old but it talks about UTM and the Cartesian coordinate system. So using the DecDeg2UTM, I convert Lat & Lon to X & coordinates as well.
I've also been trying to use the Intersect formula I found Here I took the intersect and tried to convert it to C# which I'll post at the end. However, feeding coordinates of an oval track, it doesn't seem to be working. Also, I'm not sure exactly what it's supposed to be doing. But the coordinates it returns when it does somethign like -35.xxx & 98.xxxx which out in an ocean somewhere 1000's of miles from where the track is.
I looking for answers to the following.
I assume I need to take the location recorded when a button is pressed for Start/Finish or Segment and calculate a line perpendicular to the direction the car in able to be able to do some sort of Line Intersection calculation. The Cartesian coordinates seems to calculate the bearing fairly well. But the question here is how do you get the "left and right coordinates". Also, keep in mind, an oval track may be 60 feet wide. But as mentioned an auto cross track may only be 20 ft wide and part of the track may be with 50 ft. Note I'm fine with indicating to set the points, the car needs to be going slow or stopped at the points to get an accurate coordinate. Some tracks they will have to be set while walking the track.
Based on this, should I be trying to use decimal lat lon or would utilizing the Cartesian coordinate system based on UTM be a more accurate method for what I'm trying to do?
Either one is there a .Net library or C based library with source code that has methods for making these calculations?
How can this be accurately handled. (Not that great with Math, links to code samples would help tremendously.)
Next, after I have the lines or whatever is needed for start/finish and segments, as I get GPS sign from the car racing, I need to figure out the most accurate way to tell when a car has crossed those segments. again if I'm lucky I'll get 10 hits per second but it will probably be lower. Then the vehicle speeds could vary significantly depending on the type of track and vehicle. So the GPS hit could be many feet "left or right" of a segment. Also, it could be many feet before or after a segment.
Again, if there is a GIS library out there I can feed coordinates and all this is calculated, that's would work as well as long as it's performant. If not again I'm trying to decide if it's best to break down coordinates to X Y or some geometry formulas for coordinates in decimal format. Mods, I assume there is hard data to support an answer of either way and this isn't responses aren't fully subjective to opinions.
Here is the C# code I came up with from the Script page above. I'm starting to feel UTM and the Cartesian Coordinate system would be better for accuracy and performance. But again I'm open to evidence to the contrary if it exists.
Thanks
P.S. Note GeoCoordinate is from the .Net System.Device.Location assemble. GpsData is just a class I use to convert NMEA messages into Lat, Lon, Course, NumSats, DateTime etc.
The degree Radian methods are extensions as as follows.
public static double DegreeToRadians(this double angle)
{
return Math.PI * angle / 180.0;
}
public static double RadianToDegree(this double angle)
{
return angle * (180.0 / Math.PI);
}
}
public static GeoCoordinate CalculateIntersection(GpsData p1, double brng1, GpsData p2, double brng2)
{
// see http://williams.best.vwh.net/avform.htm#Intersection
// Not sure I need to use Cosine
double _p1LatRadians = p1.Latitude.DegreeToRadians();
double _p1LonToRadians = p1.Longitude.DegreeToRadians();
double _p2LatToRadians = p2.Latitude.DegreeToRadians();
double _p2LonToRadians = p2.Longitude.DegreeToRadians();
double _brng1ToRadians = brng1.DegreeToRadians();
double _brng2ToRadians = brng2.DegreeToRadians();
double _deltaLat = _p2LatToRadians - _p1LatRadians;
double _deltaLon = _p2LonToRadians - _p1LonToRadians;
var _var1 = 2 * Math.Asin(Math.Sqrt(Math.Sin(_deltaLat / 2) * Math.Sin(_deltaLat / 2)
+ Math.Cos(_p1LatRadians) * Math.Cos(_p2LatToRadians) * Math.Sin(_deltaLon / 2) * Math.Sin(_deltaLon / 2)));
if (_var1 == 0) return null;
// initial/final bearings between points
var _finalBrng = Math.Acos((Math.Sin(_p2LatToRadians) - Math.Sin(_p1LatRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p1LatRadians)));
//if (isNaN(θa)) θa = 0; // protect against rounding
var θb = Math.Acos((Math.Sin(_p1LatRadians) - Math.Sin(_p2LatToRadians) * Math.Cos(_var1)) / (Math.Sin(_var1) * Math.Cos(_p2LatToRadians)));
var θ12 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? _finalBrng : 2 * Math.PI - _finalBrng;
var θ21 = Math.Sin(_p2LonToRadians - _p1LonToRadians) > 0 ? 2 * Math.PI - θb : θb;
var α1 = (_brng1ToRadians - θ12 + Math.PI) % (2 * Math.PI) - Math.PI; // angle 2-1-3
var α2 = (θ21 - _brng2ToRadians + Math.PI) % (2 * Math.PI) - Math.PI; // angle 1-2-3
if (Math.Sin(α1) == 0 && Math.Sin(α2) == 0) return null; // infinite intersections
if (Math.Sin(α1) * Math.Sin(α2) < 0) return null; // ambiguous intersection
α1 = Math.Abs(α1);
α2 = Math.Abs(α2);
// ... Ed Williams takes abs of α1/α2, but seems to break calculation?
var α3 = Math.Acos(-Math.Cos(α1) * Math.Cos(α2) + Math.Sin(α1) * Math.Sin(α2) * Math.Cos(_var1));
var δ13 = Math.Atan2(Math.Sin(_var1) * Math.Sin(α1) * Math.Sin(α2), Math.Cos(α2) + Math.Cos(α1) * Math.Cos(α3));
var _finalLatRadians = Math.Asin(Math.Sin(_p1LatRadians) * Math.Cos(δ13) + Math.Cos(_p1LatRadians) * Math.Sin(δ13) * Math.Cos(_brng1ToRadians));
var _lonBearing = Math.Atan2(Math.Sin(_brng1ToRadians) * Math.Sin(δ13) * Math.Cos(_p1LatRadians), Math.Cos(δ13) - Math.Sin(_p1LatRadians) * Math.Sin(_finalLatRadians));
var _finalLon = _p1LonToRadians + _lonBearing;
var _returnLat = _finalLatRadians.RadianToDegree();
var _latToDegree = _finalLon.RadianToDegree();
var _returnLon = ( _latToDegree + 540) % 360 - 180;
return new GeoCoordinate(_returnLat, _returnLon);
//return new LatLon(φ3.toDegrees(), (λ3.toDegrees() + 540) % 360 - 180); // normalise to −180..+180°
}

How to calculate distance between 2 coordinates [duplicate]

This question already has answers here:
Calculating Distance between two Latitude and Longitude GeoCoordinates
(14 answers)
Closed 8 years ago.
I need to find the distance(Km) between 2 points in windows 8.1 apps using c# so i used the function below, but the returned value not correct any help please:
public static double DistanceTo(Double latitude1, Double longitude1, Double latitude2, Double longitude2)
{
var a = latitude1 - latitude2;
var b = longitude1 - longitude2;
return Math.Sqrt(a * a + b * b);
}
You use the wrong formula. That's the reason you don't get the correct result.
The formula you use is the one we use for the calculation of the distance between two points
in the same plane and can be proved using the pythagora's theorem. However when we want to calculate the distance between two point on the surface of a sphere (we assume that the earth is a perfect sphere), we don't use this type.
Here is a link with the correct formula and an implementation in JavaScript.
Below, I have an implementation in C#
At first we have to define a method that would take as a parameter an angle and it will return it's value in radians.
public double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}
Then we could define our method for the calculation of the distance:
public static double DistanceTo(double latitude1,
double longitude1,
double latitude2,
double longitude2)
{
// The radius of the earth in Km.
// You could also use a better estimation of the radius of the earth
// using decimals digits, but you have to change then the int to double.
int R = 6371;
double f1 = ConvertToRadians(latitude1);
double f2 = ConvertToRadians(latitude2);
double df = ConvertToRadians(latitude1-latitude2);
double dl = ConvertToRadians(longitude1-longitude2);
double a = Math.Sin(dφ/2) * Math.Sin(dφ/2) +
Math.Cos(f1) * Math.Cos(f2) *
Math.Sin(dλ/2) * Math.Sin(dλ/2);
double c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1-a));
// Calculate the distance.
double d = R * c;
return d;
}
If you don't want to implement it as above, you could use the GeoCoordinate class, which
Represents a geographical location that is determined by latitude and
longitude coordinates. May also include altitude, accuracy, speed, and
course information.
If you do so, then:
var point1 = new GeoCoordinate(latitude1, longitude1);
var point2 = new GeoCoordinate(latitude2, latitude2);
and then you get the distance between point1 and point2 like below:
point1.GetDistanceTo(point2);
Try something like this:
var coord1 = new GeoCoordinate(lat1, long1);
var coord2 = new GeoCoordinate(lat2, long2);
var distance = coord1.GetDistanceTo(coord2);
Look here. Seems like a duplicate

Vehicle GPS Tracking Devices

I am looking to add a feature to a order entry system to show the distance in KM between the order location and assigned delivery van in real time.
The vans have a GPS Tracking system from High Point GPS, comes with an API to query driver location, returns in format of LAT/LONG, and location address if available.
Once I get the location I can use a web service to calculate the distance between the 2 locations, does anyone know what is the best way to get the distance between 2 locations using LAT/LONG for vehicle and address lookup for the delivery location?
You can use Google Maps to get Lat/Long of address
See answer by Thomas Clayson
How can I get latitude, longitude of a location programmatically or using a api
Then you can calculate the distance between the two sets of coordinates by using the Law of Cosines or the Haversine formula
See Law of Cosines
It depends on the other services you are already using. For example, we already use google maps to display the route, so we use their geocoding service to translate from an address to coordinates, as well as their distance service to compute distances.
Create two DbGeography instance for source and destination point (http://msdn.microsoft.com/en-us/library/system.data.spatial.dbgeography.distance(v=vs.110).aspx). Then use distance method of DbGeography for find the distance between two points.
For distance unit refer this post : System.Data.Spatial DbGeography.Distance units?
The simple answer you may find , is a simple formula :
Calculate distance between two points in google maps V3
var rad = function(x) {
return x * Math.PI / 180;
};
var getDistance = function(p1, p2) {
var R = 6378137; // Earth’s mean radius in meter
var dLat = rad(p2.lat() - p1.lat());
var dLong = rad(p2.lng() - p1.lng());
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(rad(p1.lat())) * Math.cos(rad(p2.lat())) *
Math.sin(dLong / 2) * Math.sin(dLong / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d; // returns the distance in meter
};
using google maps api will be the best solution:
https://developers.google.com/maps/documentation/distancematrix/
I've done this but in Java, probably you can port it to c# with no much effort.
This is very accurate for distances shorter than 2000 kilometers, then it can vary a little bit from the real distance. This is due to the earth curvature. But for small distances you can assume it is plain with none or very small impact in the result.
Here is a link I found useful.
And another link, an implementation of Haversine in C#.
Hope it helps.
Best regards, Federico.
public String execute(String plat1, String plon1, String plat2, String plon2) {
String distance;
double lat1, lon1, lat2, lon2;
try{
lat1 = Double.parseDouble(plat1);
lon1 = Double.parseDouble(plon1);
lat2 = Double.parseDouble(plat2);
lon2 = Double.parseDouble(plon2);
} catch (Exception e){
lat1 = 0.0d;
lon1 = 0.0d;
lat2 = 0.0d;
lon2 = 0.0d;
}
//theta and distance
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
//distance
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
dist = dist * 1.609344;
//convert to meters
dist = dist * 1000;
//output in meters
distance = Double.toString(dist);
return distance;
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
A little explanation:
(plat1, plon1) is lat and lng of point 1 or origin
(plat2, plon2) is lat and lng of point 2 or destination
the method "execute" is the one you call, it returns a string containing the distance in meters (conversion to other units can be done easily)
two assisting functions are declared as "deg2rad" and "rad2deg".

Calculate angle required to hit coordinate (x,y) from position other than (0,0) with varying elevation

I am attempting to calculate the angle required to fire a projectile in order to hit a specific coordinate.
My projectile is located a random coordinate and my target coordinate at a static coordinate.
I ended up running across the following equation on Wikipedia for calculating the angle required to hit a coordinate at (x,y) from (0,0):
I have made some attempts to understand this and other formula and attempted the following implementation (I am using c# and XNA).
double y = source.Y - target.Y;
double x = Vector2.Distance(source, target);
double v = 1440; //velocity
double g = 25; //gravity
double sqrt = (v*v*v*v) - (g*(g*(x*x) + 2*y*(v*v)));
sqrt = Math.Sqrt(sqrt);
double angleInRadians = Math.Atan(((v*v) + sqrt)/(g*x));
I have also attempted the following, which resulted in an identical angle where the values of v and g remain the same.
double targetX = target.X - source.X;
double targetY = -(target.Y - source.Y);
double r1 = Math.Sqrt((v*v*v*v) - g*(g*(target.X*target.X) + ((2*target.Y)*(v*v))));
double a1 = ((v*v) + r1)/(g*target.X);
angleInRadians = -Math.Atan(a1);
if (targetX < 0)
{
angleInRadians -= 180/180*Math.PI;
}
My conjecture is that even in my (assumed) attempt to zero out the source coordinate, that I am still not performing the calculation correctly for coordinates with a non (0,0) source and different elevations.
Below is an image that depicts my coordinate system. It is the default for XNA.
Thanks to the help in the comments the solution to find this angle ended up requiring that the positions be translated to a (0,0) based system. For anyone looking for the same scenario the final working solution was:
double x = -(source.x - target.x);
double y = (source.y - target.y);
double v = 1440; //m/s
double g = 25; //m/s
double sqrt = (v*v*v*v) - (g*(g*(x*x) + 2*y*(v*v)));
sqrt = Math.Sqrt(sqrt);
angleInRadians = Math.Atan(((v*v) + sqrt)/(g*x));
Then to convert the radians into a vector that works with XNA, perform the following conversion:
Vector2 angleVector = new Vector2(-(float)Math.Cos(angleInRadians), (float)Math.Sin(angleInRadians));
I think the real problem lies in the use of arctan. Because the range is limited to -pi/2..pi/2 results are only in the right half plane.
Use arctan2 to get the proper coordinates:
angleInRadians = Math.Atan2(((v*v) + tmp), (g*x));

Categories

Resources