I've been currently experimenting with Google maps and came across a method available to CoreLocation that Apple provides.
The method being:
func distance(from: CLLocation) Returns the distance (measured in meters) from the receiver’s location to the specified location.
Now what has peaked my interest is how this method comes to the outputted results, after converting the meters into miles. I compared the result to the distance worked out by Google maps and found it to be vastly different. My question is does the distance function work out the distance in a straight line and disregard turnings (i.e roads, motorways etc), which in essence adds to the distance calculated.
This is my implementation which uses the method mentioned above.
func testDistance(lat0: Double, long0: Double, lat1: Double, long1: Double){
let coordinate₀ = CLLocation(latitude: lat0, longitude: long0)
let coordinate₁ = CLLocation(latitude: lat1, longitude: long1)
let distanceInMeters = coordinate₀.distance(from: coordinate₁)
let distanceInMile = distanceInMeters/1609.344
print("\(distanceInMile) miles")
}
CLLocation's distance(from: CLLocation) function calculates using a straight line between the two locations (accounting for the curvature of the earth).
https://developer.apple.com/documentation/corelocation/cllocation/1423689-distance
This method measures the distance between the two locations by tracing
a line between them that follows the curvature of the Earth. The
resulting arc is a smooth curve and does not take into account
specific altitude changes between the two locations.
There are different, equally valid definitions of the distance between points. The location manager calculates distance "as the crow flies", or along the spherical surface of the earth. (Also known as "great circle" distance.)
Then there is driving distance. That accounts for the route you have to take, which is always longer than the "straight line" distance (which is actually on the curve Earth's surface.)
Related
I am new to Anylogic and I am trying to calculate the distance between two points with given latitude-longitude values. I want the distance in miles. I have found a method from the Anylogic website that is below
default double getDistance(double startLat,
double startLon,
double endLat,
double endLon)
Calculates distance by route between two specified points.
Returns:
the distance between two specified points, measured in meters.
(source:
https://help.anylogic.com/index.jsp?topic=%2Fcom.anylogic.help%2Fhtml%2Fjavadoc%2Fcom%2Fanylogic%2Fengine%2Fgis%2FIGISRouteProvider.html)
However, when I run this for two set of points with lat-long
Point 1:
latitude:41.40174, longitude: -72.0201
Point 2:
latitude:45.332, longitude:-73.2215
this gives me a distance of 4.1098062654025815 meters in anylogic; which is wrong.Could you please help me in giving insights what I might be doing wrong? Thanks
What is wrong
You are currently using the standard distance function from Utilities, which is using the inputs as cartesian coordinates and not as geographic latitutude and logitude:
public static final double getDistance(double x1,double y1,double x2,double y2)
Returns the distance between two given points (x1, y1) and (x2, y2)
Parameters:x1 - the x coordinate of the first pointy1 - the y coordinate of the first pointx2 - the x coordinate of the second pointy2 - the y coordinate of the second point
Returns:the distance between points
How to fix it
In order to calculate geographic distances with latitude and longitude, you will have to access the functions that come with the ShapeGISMap object:
double getDistanceByRoute(double latFrom, double lonFrom, double latTo, double lonTo)
Calculates length of route from one point to another.
double getDistance(double latFrom, double lonFrom, double latTo, double lonTo)
Returns distance, in meters, between 2 given points
You can access them by adding a GIS Map from the SpaceMarkup palette (the instance here named map), and referencing it:
map.getDistanceByRoute(41.40174,-72.0201,45.332,-73.2215);
Additional Hint
You can always check if you are really using the correct function in your context by using Java auto completion (Type the first part of the function name, then CTRL + Space Bar) and having a look in the JavaDoc that is then showing:
I have a number of marker coordinates stored in array. I want to be able to locate the markers that are near the user on the map. For example there are 3 markers near user. I know that google supply a distance matrix api which calculate the distance (2min from user). the only solution i found was in javascript. If anyone can guide me in the right direction that would be very helpful. Thank you in advance.
You need to use distance(from location: CLLocation) of CLLocation class. Its in CLLocation class
open func distance(from location: CLLocation) -> CLLocationDistance
Returns the distance (in meters) from the receiver’s location to the specified location.
Here is the Apple's Link
Usage
Swift 3.x code
let us assume there is a variable of CLLocation called userLocation in which the lat and long of user location is there. So to calculate the distance from userLocation to your markerLocation and there is an object called marker of GMSMarker class
let markerLocation = CLLocation(latitude: marker.position.latitude, longitude: marker.position.longitude)
let metres = userLocation.distance(from: markerLocation)
print(metres) //will be in metres
Here you will get the distance between your marker position and your userLocation. So you can write your logic accordingly.
Say I have a square which consists of four CLLocationCoordinate2D points, which are in lat, lon, and I want to find the area of the square in meters. I convert the CLLocationCoordinate2D points into MKMapPoints, and I find the area in X-Y space. However, the area I find is in the units of MKMapPoint, which don't directly translate to meters. How can I translate this area in MKMapPoint-space back into meters?
The MapKit function MKMetersBetweenMapPoints makes this easier.
For example, if you wanted to get the area of the currently displayed region:
MKMapPoint mpTopLeft = mapView.visibleMapRect.origin;
MKMapPoint mpTopRight = MKMapPointMake(
mapView.visibleMapRect.origin.x + mapView.visibleMapRect.size.width,
mapView.visibleMapRect.origin.y);
MKMapPoint mpBottomRight = MKMapPointMake(
mapView.visibleMapRect.origin.x + mapView.visibleMapRect.size.width,
mapView.visibleMapRect.origin.y + mapView.visibleMapRect.size.height);
CLLocationDistance hDist = MKMetersBetweenMapPoints(mpTopLeft, mpTopRight);
CLLocationDistance vDist = MKMetersBetweenMapPoints(mpTopRight, mpBottomRight);
double vmrArea = hDist * vDist;
The documentation states that the function takes "into account the curvature of the Earth."
You can use the Haversine formula to calculate it, assuming that the earth is a perfect sphere.
To understand how lat/lon vs meters works in the context of the earth, you may find it interesting to read about Nautical miles.
You can find some more resources and some sample code by googling objective-c Haversine formula.
Enjoy!
On the iPhone, I get the user's location in decimal degrees, for example: latitude 39.470920 and longitude = -0.373192; That's point A.
I need to create a line with another GPS coordinate, also in decimal degrees, point B. Then, calculate the distance (perpendicular) between the line from A to B and another point C.
The problem is I get confused with the values in degrees. I would like to have the result in meters. What's the conversion needed? How will the final formula to compute this look like?
Why don't you use CLLocations distanceFromLocation: method? It will tell you the precise distance between the receiver and another CLLocation.
CLLocation *locationA = [[CLLocation alloc] initWithLatitude:12.123456 longitude:12.123456];
CLLocation *locationB = [[CLLocation alloc] initWithLatitude:21.654321 longitude:21.654321];
CLLocationDistance distanceInMeters = [locationA distanceFromLocation:locationB];
// CLLocation is aka double
[locationA release];
[locationB release];
It's as easy as that.
(CLLocationDistance)distanceFromLocation:(const CLLocation *)location is the method to get the distance from on CLLocation to another.
Your problem is also of finding the shortest line between a line (A,B) and point C.
I guess if your 3 CLLocations are near ( less than a few kilometers apart), you can do the math "as if" the coordinates are points on a single plane, and use this in C++, or this or this and just use the CLLocations "as if" they were x and y coordinates on a plane.
If your coordinates are far away, or exact accuracy is important then the spherical shape of the earth matters, and you need to do things using great circle distance and other geometry on the face of a sphere.
Swift 3.0+
Only calculate distance between two coordinates:
let distance = source.distance(from: destination)
When you have array of locations:
To get distance from array of points use below reduce method.
Here locations is array of type CLLocation.
let calculatedDistance = locations.reduce((0, locations[0])) { ($0.0 + $0.1.distance(from: $1), $1)}.0
Here you will get distance in meters.
I wanted to test the mapKit and wanted to make my own overlay to display the accuracy of my position.
If i have a zoom factor of for example .005 which radius does my circle around me has to have(If my accuracy is for example 500m)?
Would be great to get some help :)
Thanks a lot.
Look at the documentation for MKCoordinateSpan, which is part of the map's region property. One degree of latitude is always approx. 111 km, so converting the latitudeDelta to meters and then getting to the meters per pixel should be easy. For longitudinal values it is not quite so easy as the distance covered by one degree of longitude varies between 111 km (at the equator) and 0 km (at the poles).
My way to get meters per pixel:
MKMapView *mapView = ...;
CLLocationCoordinate2D coordinate = ...;
MKMapRect mapRect = mapView.visibleMapRect;
CLLocationDistance metersPerMapPoint = MKMetersPerMapPointAtLatitude(coordinate.latitude);
CGFloat metersPerPixel = metersPerMapPoint * mapRect.size.width / mapView.bounds.size.width;
To add to another answer, a difference of one minute of latitude corresponds to one nautical mile: that's how the nautical mile was defined. So, converting to statute miles, 1 nautical mile = 1.1508 statue miles, or 6076.1 ft. or 1852 meters.
When you go to longitude, the size of the longitude circles around the Earth shrink as latitude increases, as was noted on the previous answer. The correct factor is that
1 minute of longitude = (1852 meters)*cos(theta),
where theta is the latitude.
Of course, the Earth is not a perfect sphere, but the simple calculation above would never be off by more than 1%.