can I calculate accurate distance between two latitude and longitude inside a house within 5 meters? [duplicate] - swift

This question already exists:
I want to build something like that if a user enters in a room he recieve a notification in swift ios is it possible?
Closed 3 months ago.
I want to calculate distance between two coordinates within 5 meters or even within one meters is it possible
I have tried haversine formula but not getting the desired result
func calculateDistanceWithHaversin(crrLat: Double, crrLong: Double, desLat: Double = 23.1780068, desLong: Double = 75.7865060, radius: Double = 6367444.7) -> Double {
print("CrrLat \(crrLat) = CrrLong = \(crrLong)")
let haversin = { (angle: Double) -> Double in
return (1 - cos(angle))/2
}
let ahaversin = { (angle: Double) -> Double in
return 2 * asin(sqrt(angle))
}
// degree to radian
let dToR = { (angle: Double) -> Double in
return (angle / 360) * 2 * .pi
}
let lat1 = dToR(crrLat)
let lon1 = dToR(crrLong)
let lat2 = dToR(desLat)
let lon2 = dToR(desLong)
return radius * ahaversin(haversin(lat2 - lat1) + cos(lat1) * cos(lat2) * haversin(lon2 - lon1))
}
i have tried this also
func calculateDistance(crrLat: Double, crrLong: Double) {
let destinationLocation = CLLocation(latitude: 23.1780068, longitude: 75.7865060)
let currentLocation = CLLocation(latitude: crrLat, longitude: crrLong)
distance = currentLocation.distance(from: destinationLocation)
print(String(format: "The distance to my buddy is %.02f m", distance))
}

You can calculate distance with this Builtin Function provided by CoreLocation . The provided distance will be in meters
import CoreLocation
let locationOne = CLLocation(latitude: 37.899, longitude: 74.8989)
let locationTwo = CLLocation(latitude: 38.0900, longitude: 78.98898)
let distance = locationOne.distance(from: locationTwo)

Related

Getting An Arbitrary Type From Reduce

I'm doing a very simple operation. I'm sorting through a bunch of locations in a map to create an enclosing circle, like so:
var maxLong: Double = -180
var maxLat: Double = -180
var minLong: Double = 180
var minLat: Double = 180
for coord in inCoordinates {
maxLong = max(coord.longitude, maxLong)
maxLat = max(coord.latitude, maxLat)
minLong = min(coord.longitude, minLong)
minLat = min(coord.latitude, minLat)
}
let nw: CLLocation = CLLocation(latitude: maxLat, longitude: minLong)
let se: CLLocation = CLLocation(latitude: minLat, longitude: maxLong)
let center = CLLocationCoordinate2D(latitude: (maxLat + minLat) / 2.0, longitude: (maxLong + minLong) / 2.0)
let radiusInMeters = abs(nw.distance(from: se)) / 2.0
return MKCircle(center: center, radius: radiusInMeters)
Pretty straightforward (Yeah, I know about the IDL issue, but I want to keep this simple).
What I'd like to know, is if there were some way I could boil the loop into a variant of reduce, where you would end up with something like this:
let enclosingRect: MKMapRect = inCoordinates.magikalReduce {
// Magic Happens Here -Queue Doug Henning GIF
}
So the returned rect contains the distilled points.
Yeah, I know that I can simply extend Array (with maybe a type qualifier) to do this with a calculated property, but that sort of defeats the purpose of this. The above is fairly efficient, and I'd rather not add overhead, just to be fancy (Which means, even if I could do it, it might be too inefficient to use).
This is more of a curiosity exploration than a technical need. The above code does fine for me, and is relatively zippy.
Do you mean
// calculate the enclosing rect with `reduce` and `union`, you have to create an `MKMapRect` from each coordinate
let enclosingRect = inCoordinates.reduce(MKMapRect.null) { $0.union(MKMapRect(origin: MKMapPoint($1), size: MKMapSize())) }
You can create a struct for holding the min/max longitude and latitude values, then use reduce, where you use the initial values for these for creating an initial result, then creating an updated version of the struct with the necessary min/max calculations.
struct MinMaxCoordinates {
let maxLong:Double
let maxLat:Double
let minLong:Double
let minLat:Double
}
let minMaxCoordinates = inCoordinates.reduce(MinMaxCoordinates(maxLong: -180, maxLat: -180, minLong: 180, minLat: 180), {minMax, coord in
return MinMaxCoordinates(maxLong: max(minMax.maxLong, coord.longitude), maxLat: max(minMax.maxLat, coord.latitude), minLong: min(minMax.minLong, coord.longitude), minLat: max(minMax.minLat, coord.latitude))
})
let nw: CLLocation = CLLocation(latitude: minMaxCoordinates.maxLat, longitude: minMaxCoordinates.minLong)
let se: CLLocation = CLLocation(latitude: minMaxCoordinates.minLat, longitude: minMaxCoordinates.maxLong)
let center = CLLocationCoordinate2D(latitude: (minMaxCoordinates.maxLat + minMaxCoordinates.minLat) / 2.0, longitude: (minMaxCoordinates.maxLong + minMaxCoordinates.minLong) / 2.0)
let radiusInMeters = abs(nw.distance(from: se)) / 2.0
return MKCircle(center: center, radius: radiusInMeters)

Get all locations within certain radius from SQLite Database in XCode

I have a SQLite Database which contains latitude and longitude of several locations.
I want to find the latitude and longitude of all locations which fall within 15km radius from my current location from my SQLite Database.
What will be my SQLite Query for this?
One degree difference of latitude is equal to 111 km distance, and One degree difference of longitude is equal to 94 km. So Now check for all the latitude which are at (+/-)(15/111) difference and longitudes which are (+/-)(15/94) difference from your current location.
Important link for reference.
For anyone still looking for an answer:
You can get nearby locations with this method adapted from #breceivemail's answer [JAVA]
Here is the translated version in Swift:
private func calculateDerivedPosition(point: CGPoint, range: Double, bearing: Double)-> CGPoint {
let EarthRadius: Double = 6371000
let latA = Double(point.x.degreesToRadians)
let lonA = Double(point.y.degreesToRadians)
let angularDistance = range / EarthRadius
let trueCourse = bearing.degreesToRadians
var lat = asin(sin(latA) * cos(angularDistance) +
cos(latA) * sin(angularDistance) *
cos(trueCourse))
let dlon = atan2(sin(trueCourse) * sin(angularDistance) * cos(latA),
cos(angularDistance) - sin(latA) * sin(lat))
var lon = ((lonA + dlon + Double.pi).truncatingRemainder(dividingBy: (Double.pi * 2))) - Double.pi
lat = lat.radiansToDegrees
lon = lon.radiansToDegrees
let newPoint = CGPoint(x: lat, y: lon)
return newPoint
}
radiansToDegree Extension
And You can use it like this with FMDB (or any Sqlite lib):
let center = CGPoint(x: currentLocation.latitude, y: currentLocation.longitude)
let mult: Double = 1 // mult = 1.1 is more reliable
let radius: Double = 5000 //in meters
let point1 = calculateDerivedPosition(point: center, range: radius * mult, bearing: 0)
let point2 = calculateDerivedPosition(point: center, range: radius * mult, bearing: 90)
let point3 = calculateDerivedPosition(point: center, range: radius * mult, bearing: 180)
let point4 = calculateDerivedPosition(point: center, range: radius * mult, bearing: 270)
let result = try!db.executeQuery("SELECT * FROM items WHERE lat > ? AND lat < ? AND lng < ? AND lng > ?" , values: [point3.x, point1.x, point2.y, point4.y])
Note: The results aren't sorted.
To arrange them in Ascending order, store all the distcnace in a dictionary with key. like,
distanceDic = [[NSMutableDictionary alloc]initWithObjectsAndKeys:[NSNumber numberWithFloat:distanceVal],#"distance",nil];
[distanceArray addObject:distanceDic];
Here, distanceDic is my Dictionary and distaceVal is string containing distance.
distanceArray is NSMutableArray Containing Distance.
Now Sort the distanceDic like,
NSArray *array = [NSArray arrayWithArray:[distanceArray mutableCopy]]; // Copying NSMutableArray to NSArray.
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"distance" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
array = [array sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"#The Final Distance Array After Sorting :%#",array);
This will give you resulting Distance Array sorted in Ascending order.

Calculate bearing between two locations

I want to calculate bearing between two location in Swift. I tried some code but it do not work. I searched about this problem but I didn't find any result about this.
func calculat(userlocation:CLLocation){
let latuserlocation: () = DegreesToRadians(userlocation.coordinate.latitude)
let lonuserlocatioc: () = DegreesToRadians(userlocation.coordinate.longitude)
latitude = NSString (string: places[activePlace]["lat"]!).doubleValue
longitude = NSString (string: places[activePlace]["lon"]!).doubleValue
let targetedPointLatitude: () = DegreesToRadians(latitude)
let targetedPointlongitude: () = DegreesToRadians(longitude)
let dlon = lonuserlocatioc - targetedPointlongitude
let y = sin(dLon) * cos(targetedPointLatitude);
let x = cos(latuserlocation) * sin(targetedPointLatitude) - sin(latuserlocation) * cos(targetedPointLatitude) * cos(dLon);
let radiansBearing = atan2(y, x);
return RadiansToDegrees(radiansBearing)
The error on let dlon = lonuserlocatioc - targetedPointlongitude is:
(cannot invoke '-' with an argument list of type '((), ())')
Compared to CLLocation Category for Calculating Bearing w/ Haversine function, your dlon is different. That answer has
let dlon = targetedPointlongitude - lonuserlocatioc
I don't know if that's your problem but it looks odd.
Swift function like this;
func radians(n: Double) -> Double{
return n * (M_PI / 180);
}
func degrees(n: Double) -> Double{
return n * (180 / M_PI);
}
func logC(val:Double,forBase base:Double) -> Double {
return log(val)/log(base);
}
func getBearing(startLat: Double,startLon:Double,endLat: Double,endLon: Double) -> Double{
var s_LAT: Double , s_LON: Double, e_LAT: Double, e_LON: Double, d_LONG: Double, d_PHI: Double;
s_LAT = startLat;
s_LON = startLon;
e_LAT = endLat;
e_LON = endLon;
d_LONG = e_LON - s_LON;
d_PHI = logC(tan(e_LAT/2.0+M_PI/4.0)/tan(s_LAT/2.0+M_PI/4.0),forBase :M_E);
if (abs(d_LONG)>M_PI){
if(d_LONG>0.0){
d_LONG = -(2.0 * M_PI - d_LONG);
}else{
d_LONG = (2.0 * M_PI - d_LONG);
}
}
return degrees(atan2(d_LONG, d_PHI)+360.0)%360.0;
}

Calculation that calculates the new latitude and longitude based on a starting point, bearing and distance?

Does anyone have a calculation that calculates the new
latitude and longitude based on a starting point, bearing and
distance?
I would greatly appreciate any help people might have.
I've used the code from Calculate new coordinate x meters and y degree away from one coordinate:
- (CLLocationCoordinate2D)coordinateFromCoord:(CLLocationCoordinate2D)fromCoord
atDistanceKm:(double)distanceKm
atBearingDegrees:(double)bearingDegrees
{
double distanceRadians = distanceKm / 6371.0;
//6,371 = Earth's radius in km
double bearingRadians = [self radiansFromDegrees:bearingDegrees];
double fromLatRadians = [self radiansFromDegrees:fromCoord.latitude];
double fromLonRadians = [self radiansFromDegrees:fromCoord.longitude];
double toLatRadians = asin(sin(fromLatRadians) * cos(distanceRadians)
+ cos(fromLatRadians) * sin(distanceRadians) * cos(bearingRadians) );
double toLonRadians = fromLonRadians + atan2(sin(bearingRadians)
* sin(distanceRadians) * cos(fromLatRadians), cos(distanceRadians)
- sin(fromLatRadians) * sin(toLatRadians));
// adjust toLonRadians to be in the range -180 to +180...
toLonRadians = fmod((toLonRadians + 3*M_PI), (2*M_PI)) - M_PI;
CLLocationCoordinate2D result;
result.latitude = [self degreesFromRadians:toLatRadians];
result.longitude = [self degreesFromRadians:toLonRadians];
return result;
}
- (double)radiansFromDegrees:(double)degrees
{
return degrees * (M_PI/180.0);
}
- (double)degreesFromRadians:(double)radians
{
return radians * (180.0/M_PI);
}
Or in Swift:
extension CLLocationCoordinate2D {
func adjusted(distance: Double, degrees: Double) -> CLLocationCoordinate2D {
let distanceRadians = distance / 6_371 // 6,371 == Earth's radius in km
let bearingRadians = degrees.radians
let fromLatRadians = latitude.radians
let fromLonRadians = longitude.radians
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))
// adjust toLonRadians to be in the range -180 to +180...
toLonRadians = fmod((toLonRadians + 3 * .pi), (2 * .pi)) - .pi
return CLLocationCoordinate2D(latitude: toLatRadians.degrees, longitude: toLonRadians.degrees)
}
}
extension CLLocationDegrees {
var radians: Double { self * .pi / 180 }
}
extension Double {
var degrees: CLLocationDegrees { self * 180 / .pi }
}
You will find all the calculations you could possibly want (including explanations etc) at http://www.movable-type.co.uk/scripts/latlong.html
The code you need is (in JavaScript) under the heading "Destination point given distance and bearing from start point". Excerpting:
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
Math.cos(lat1)*Math.sin(d/R)*Math.cos(brng) );
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat1),
Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));
Where R = radius of the earth, d = distance (in same units), and lat/long are in radians (since that's what the sin function expects). You go from degrees to radians with
radians = pi * degrees / 180;
You should be able to take it from here. Do look at the link I gave for more info.

CLLocation Category for Calculating Bearing w/ Haversine function

I'm trying to write a category for CLLocation to return the bearing to another CLLocation.
I believe I'm doing something wrong with the formula (calculous is not my strong suit). The returned bearing is always off.
I've been looking at this question and tried applying the changes that were accepted as a correct answer and the webpage it references:
Calculating bearing between two CLLocationCoordinate2Ds
http://www.movable-type.co.uk/scripts/latlong.html
Thanks for any pointers. I've tried incorporating the feedback from that other question and I'm still just not getting something.
Thanks
Here's my category -
----- CLLocation+Bearing.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface CLLocation (Bearing)
-(double) bearingToLocation:(CLLocation *) destinationLocation;
-(NSString *) compassOrdinalToLocation:(CLLocation *) nwEndPoint;
#end
---------CLLocation+Bearing.m
#import "CLLocation+Bearing.h"
double DegreesToRadians(double degrees) {return degrees * M_PI / 180;};
double RadiansToDegrees(double radians) {return radians * 180/M_PI;};
#implementation CLLocation (Bearing)
-(double) bearingToLocation:(CLLocation *) destinationLocation {
double lat1 = DegreesToRadians(self.coordinate.latitude);
double lon1 = DegreesToRadians(self.coordinate.longitude);
double lat2 = DegreesToRadians(destinationLocation.coordinate.latitude);
double lon2 = DegreesToRadians(destinationLocation.coordinate.longitude);
double dLon = lon2 - lon1;
double y = sin(dLon) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
double radiansBearing = atan2(y, x);
return RadiansToDegrees(radiansBearing);
}
Your code seems fine to me. Nothing wrong with the calculous. You don't specify how far off your results are, but you might try tweaking your radian/degrees converters to this:
double DegreesToRadians(double degrees) {return degrees * M_PI / 180.0;};
double RadiansToDegrees(double radians) {return radians * 180.0/M_PI;};
If you are getting negative bearings, add 2*M_PI to the final result in radiansBearing (or 360 if you do it after converting to degrees). atan2 returns the result in the range -M_PI to M_PI (-180 to 180 degrees), so you might want to convert it to compass bearings, using something like the following code
if(radiansBearing < 0.0)
radiansBearing += 2*M_PI;
This is a porting in Swift of the Category at the beginning:
import Foundation
import CoreLocation
public extension CLLocation{
func DegreesToRadians(_ degrees: Double ) -> Double {
return degrees * M_PI / 180
}
func RadiansToDegrees(_ radians: Double) -> Double {
return radians * 180 / M_PI
}
func bearingToLocationRadian(_ destinationLocation:CLLocation) -> Double {
let lat1 = DegreesToRadians(self.coordinate.latitude)
let lon1 = DegreesToRadians(self.coordinate.longitude)
let lat2 = DegreesToRadians(destinationLocation.coordinate.latitude);
let lon2 = DegreesToRadians(destinationLocation.coordinate.longitude);
let dLon = lon2 - lon1
let y = sin(dLon) * cos(lat2);
let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
let radiansBearing = atan2(y, x)
return radiansBearing
}
func bearingToLocationDegrees(destinationLocation:CLLocation) -> Double{
return RadiansToDegrees(bearingToLocationRadian(destinationLocation))
}
}
Here is another implementation
public func bearingBetweenTwoPoints(#lat1 : Double, #lon1 : Double, #lat2 : Double, #lon2: Double) -> Double {
func DegreesToRadians (value:Double) -> Double {
return value * M_PI / 180.0
}
func RadiansToDegrees (value:Double) -> Double {
return value * 180.0 / M_PI
}
let y = sin(lon2-lon1) * cos(lat2)
let x = (cos(lat1) * sin(lat2)) - (sin(lat1) * cos(lat2) * cos(lat2-lon1))
let degrees = RadiansToDegrees(atan2(y,x))
let ret = (degrees + 360) % 360
return ret;
}
Working Swift 3 and 4
Tried so many versions and this one finally gives correct values!
extension CLLocation {
func getRadiansFrom(degrees: Double ) -> Double {
return degrees * .pi / 180
}
func getDegreesFrom(radians: Double) -> Double {
return radians * 180 / .pi
}
func bearingRadianTo(location: CLLocation) -> Double {
let lat1 = self.getRadiansFrom(degrees: self.coordinate.latitude)
let lon1 = self.getRadiansFrom(degrees: self.coordinate.longitude)
let lat2 = self.getRadiansFrom(degrees: location.coordinate.latitude)
let lon2 = self.getRadiansFrom(degrees: location.coordinate.longitude)
let dLon = lon2 - lon1
let y = sin(dLon) * cos(lat2)
let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
var radiansBearing = atan2(y, x)
if radiansBearing < 0.0 {
radiansBearing += 2 * .pi
}
return radiansBearing
}
func bearingDegreesTo(location: CLLocation) -> Double {
return self.getDegreesFrom(radians: self.bearingRadianTo(location: location))
}
}
Usage:
let degrees = location1.bearingDegreesTo(location: location2)
This is an another CLLocation extension can be used in Swift 3 and Swift 4
public extension CLLocation {
func degreesToRadians(degrees: Double) -> Double {
return degrees * .pi / 180.0
}
func radiansToDegrees(radians: Double) -> Double {
return radians * 180.0 / .pi
}
func getBearingBetweenTwoPoints(point1: CLLocation, point2: CLLocation) -> Double {
let lat1 = degreesToRadians(degrees: point1.coordinate.latitude)
let lon1 = degreesToRadians(degrees: point1.coordinate.longitude)
let lat2 = degreesToRadians(degrees: point2.coordinate.latitude)
let lon2 = degreesToRadians(degrees: point2.coordinate.longitude)
let dLon = lon2 - lon1
let y = sin(dLon) * cos(lat2)
let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon)
let radiansBearing = atan2(y, x)
return radiansToDegrees(radians: radiansBearing)
}
}
I use the Law of Cosines in Swift. It runs faster than Haversine and its result is extremely similar. Variation of 1 metre on huge distances.
Why do I use the Law of Cosines:
Run fast (because there is no sqrt functions)
Precise enough unless you do some astronomy
Perfect for a background task
func calculateDistance(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D) -> Double {
let π = M_PI
let degToRad: Double = π/180
let earthRadius: Double = 6372797.560856
// Law of Cosines formula
// d = r . arc cos (sin 𝜑A sin 𝜑B + cos 𝜑A cos 𝜑B cos(𝜆B - 𝜆A) )
let 𝜑A = from.latitude * degToRad
let 𝜑B = to.latitude * degToRad
let 𝜆A = from.longitude * degToRad
let 𝜆B = to.longitude * degToRad
let angularDistance = acos(sin(𝜑A) * sin(𝜑B) + cos(𝜑A) * cos(𝜑B) * cos(𝜆B - 𝜆A) )
let distance = earthRadius * angularDistance
return distance
}
Worth mentioning that if you are using Google map GMSMapView, there's an out-of-the-box solution using the GMSGeometryHeading method:
GMSGeometryHeading(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D)
Returns the initial heading (degrees clockwise of North) at from of
the shortest path to to.
Implemented this in Swift 5. Focus is on accuracy, not speed, but it runs in real time np.
let earthRadius: Double = 6372456.7
let degToRad: Double = .pi / 180.0
let radToDeg: Double = 180.0 / .pi
func calcOffset(_ coord0: CLLocationCoordinate2D,
_ coord1: CLLocationCoordinate2D) -> (Double, Double) {
let lat0: Double = coord0.latitude * degToRad
let lat1: Double = coord1.latitude * degToRad
let lon0: Double = coord0.longitude * degToRad
let lon1: Double = coord1.longitude * degToRad
let dLat: Double = lat1 - lat0
let dLon: Double = lon1 - lon0
let y: Double = cos(lat1) * sin(dLon)
let x: Double = cos(lat0) * sin(lat1) - sin(lat0) * cos(lat1) * cos(dLon)
let t: Double = atan2(y, x)
let bearing: Double = t * radToDeg
let a: Double = pow(sin(dLat * 0.5), 2.0) + cos(lat0) * cos(lat1) * pow(sin(dLon * 0.5), 2.0)
let c: Double = 2.0 * atan2(sqrt(a), sqrt(1.0 - a));
let distance: Double = c * earthRadius
return (distance, bearing)
}
func translateCoord(_ coord: CLLocationCoordinate2D,
_ distance: Double,
_ bearing: Double) -> CLLocationCoordinate2D {
let d: Double = distance / earthRadius
let t: Double = bearing * degToRad
let lat0: Double = coord.latitude * degToRad
let lon0: Double = coord.longitude * degToRad
let lat1: Double = asin(sin(lat0) * cos(d) + cos(lat0) * sin(d) * cos(t))
let lon1: Double = lon0 + atan2(sin(t) * sin(d) * cos(lat0), cos(d) - sin(lat0) * sin(lat1))
let lat: Double = lat1 * radToDeg
let lon: Double = lon1 * radToDeg
let c: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: lat,
longitude: lon)
return c
}
I found that Haversine nailed the distance versus CLLocation's distance method, but didn't provide a bearing ready-to-use with CL. So I'm not using it for the bearing. This gives the most accurate measurement I've encountered from all the math I've tried. The translateCoord method will also precisely plot a new point given an origin, distance in meters, and a bearing in degrees.