objective manager corelocation iphone cocoa-touch core-location latitude-longitude

iphone - corelocation - locationmanager ios



Moviendo un CLLocation por x metros (7)

Tengo una ubicación CL definida, y me gustaría mover ese punto x metros hacia el este y metros hacia el sur. ¿Cómo puedo lograr eso?


Gran publicación, aquí está el envoltorio de Obj-C para aquellos que aman copiar / pegar:

- (CLLocationCoordinate2D) locationWithBearing:(float)bearing distance:(float)distanceMeters fromLocation:(CLLocationCoordinate2D)origin { CLLocationCoordinate2D target; const double distRadians = distanceMeters / (6372797.6); // earth radius in meters float lat1 = origin.latitude * M_PI / 180; float lon1 = origin.longitude * M_PI / 180; float lat2 = asin( sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(bearing)); float lon2 = lon1 + atan2( sin(bearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2) ); target.latitude = lat2 * 180 / M_PI; target.longitude = lon2 * 180 / M_PI; // no need to normalize a heading in degrees to be within -179.999999° to 180.00000° return target; }


Hay una función de C que está cerca de lo que estás preguntando pero que toma una marcación y distancia. Está en mi clase de UtilitiesGeo en github . Pasaría la latitud y la longitud de su ubicación CLL y luego creará una ubicación CLL nueva del lat2 y lon2 resultantes que devuelve:

/*------------------------------------------------------------------------- * Given a starting lat/lon point on earth, distance (in meters) * and bearing, calculates destination coordinates lat2/lon2. * * all params in degrees *-------------------------------------------------------------------------*/ void destCoordsInDegrees(double lat1, double lon1, double distanceMeters, double bearing, double* lat2, double* lon2);

Si no puede usar eso, eche un vistazo a los algoritmos que se derivaron de here y here y quizás pueda modificarlo o esos sitios podrían tener algo más cercano a sus necesidades.


Implementación rápida utilizando la estructura de Measurement para hacer las conversiones entre grados y radianes.

class GPSLocation { public class func degreesToRadians(degrees: Double) -> Double { return Measurement(value: degrees, unit: UnitAngle.degrees).converted(to: .radians).value } public class func radiansToDegrees(radians: Double) -> Double { return Measurement(value: radians, unit: UnitAngle.radians).converted(to: .degrees).value } public class func location(location: CLLocation, byMovingDistance distance: Double, withBearing bearingDegrees:CLLocationDirection) -> CLLocation { let distanceRadians: Double = distance / 6372797.6 let bearingRadians: Double = GPSLocation.degreesToRadians(degrees: bearingDegrees) let lat1 = GPSLocation.degreesToRadians(degrees: location.coordinate.latitude) let lon1 = GPSLocation.degreesToRadians(degrees: location.coordinate.longitude) let lat2 = GPSLocation.radiansToDegrees(radians:asin(sin(lat1) * cos(distanceRadians) + cos(lat1) * sin(distanceRadians) * cos(bearingRadians))) let lon2 = GPSLocation.radiansToDegrees(radians:lon1 + atan2(sin(bearingRadians) * sin(distanceRadians * cos(lat1)), cos(distanceRadians) - sin(lat1) * sin(lat2))) return CLLocation(latitude: lat2, longitude: lon2) } }


Ligero ajuste a la respuesta de @CocoaChris: ahora una categoría en CLLocation, y usando las unidades integradas.

#import <CoreLocation/CoreLocation.h> @interface CLLocation (Movement) - (CLLocation *)locationByMovingDistance:(double)distanceMeters withBearing:(CLLocationDirection)bearingDegrees; @end @implementation CLLocation (Movement) - (CLLocation *)locationByMovingDistance:(double)distanceMeters withBearing:(CLLocationDirection)bearingDegrees { const double distanceRadians = distanceMeters / (6372797.6); // earth radius in meters const double bearingRadians = bearingDegrees * M_PI / 180; float lat1 = self.coordinate.latitude * M_PI / 180; float lon1 = self.coordinate.longitude * M_PI / 180; float lat2 = asin(sin(lat1) * cos(distanceRadians) + cos(lat1) * sin(distanceRadians) * cos(bearingRadians)); float lon2 = lon1 + atan2(sin(bearingRadians) * sin(distanceRadians) * cos(lat1), cos(distanceRadians) - sin(lat1) * sin(lat2) ); return [[CLLocation alloc] initWithLatitude:lat2 * 180 / M_PI longitude:lon2 * 180 / M_PI]; } @end


Solución rápida mejorada a la respuesta de Peters. Sólo la corrección es que el rodamiento debe ser radian mientras se ha realizado el cálculo.

func locationWithBearing(bearing:Double, distanceMeters:Double, origin:CLLocationCoordinate2D) -> CLLocationCoordinate2D { let distRadians = distanceMeters / (6372797.6) var rbearing = bearing * M_PI / 180.0 let lat1 = origin.latitude * M_PI / 180 let lon1 = origin.longitude * M_PI / 180 let lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(rbearing)) let lon2 = lon1 + atan2(sin(rbearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2)) return CLLocationCoordinate2D(latitude: lat2 * 180 / M_PI, longitude: lon2 * 180 / M_PI) }


Una conversión a Swift, tomada de esta respuesta :

func locationWithBearing(bearing:Double, distanceMeters:Double, origin:CLLocationCoordinate2D) -> CLLocationCoordinate2D { let distRadians = distanceMeters / (6372797.6) // earth radius in meters let lat1 = origin.latitude * M_PI / 180 let lon1 = origin.longitude * M_PI / 180 let lat2 = asin(sin(lat1) * cos(distRadians) + cos(lat1) * sin(distRadians) * cos(bearing)) let lon2 = lon1 + atan2(sin(bearing) * sin(distRadians) * cos(lat1), cos(distRadians) - sin(lat1) * sin(lat2)) return CLLocationCoordinate2D(latitude: lat2 * 180 / M_PI, longitude: lon2 * 180 / M_PI) }

Morgan Chen escribió esto:

Todas las matemáticas en este método se hacen en radianes. Al comienzo del método, lon1 y lat1 también se convierten a radianes para este propósito. El rodamiento está en radianes también. Tenga en cuenta que este método tiene en cuenta la curvatura de la Tierra, que realmente no necesita hacer para distancias pequeñas.


Una solución más simple es usar MKMapPoints.

Convierta sus coordenadas originales y cualquier distancia de desplazamiento que necesite a MKMapPoints utilizando esto:

let coordinatesInMapPoints = MKMapPointForCoordinate(CLLocationCoordinate2D) let distancesInMapPoints = yourDistanceInMeters * MKMapPointsPerMeterAtLatitude(CLLocationDegrees) // Do this for both x and y directions if needed.

Luego cree un nuevo MKMapPoint simplemente agregando sus distancias de desplazamiento a sus coordenadas originales:

let newCoordinatesInMapPoints = MKMapPointMake(coordinatesInMapPoints.x + distancesInMapPoints, coordinatesInMapPoints.y)

Finalmente, vuelva a convertir las nuevas coordenadas de un MKMapPoint a CLLocationCoordinate2D:

let newCoordinate = MKCoordinateForMapPoint(newCoordinatesInMapPoints)

No se requieren cálculos de conversión complejos.