Calcule la nueva coordenada x metros y el grado lejos de una coordenada

Debo extrañar algo en los documentos, pensé que esto debería ser fácil …

Si tengo una coordenada y quiero obtener una nueva coordenada x metros de distancia, en alguna dirección. ¿Cómo hago esto?

Estoy buscando algo así como

-(CLLocationCoordinate2D) translateCoordinate:(CLLocationCoordinate2D)coordinate translateMeters:(int)meters translateDegrees:(double)degrees;

¡Gracias!

Lamentablemente, no hay tal función en la API, por lo que tendrá que escribir la suya.

Este sitio ofrece varios cálculos que involucran latitud / longitud y código JavaScript de muestra. Específicamente, la sección titulada “Distancia y distancia entre el punto de destino y el rumbo desde el punto de partida” muestra cómo calcular lo que está preguntando.

El código JavaScript se encuentra en la parte inferior de la página y aquí hay una forma posible de convertirlo a Objective-C:

 - (double)radiansFromDegrees:(double)degrees { return degrees * (M_PI/180.0); } - (double)degreesFromRadians:(double)radians { return radians * (180.0/M_PI); } - (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; } 

En el código JS, contiene este enlace que muestra un cálculo más preciso para distancias superiores a 1/4 de la circunferencia de la Tierra.

También tenga en cuenta que el código anterior acepta la distancia en km, así que asegúrese de dividir los metros entre 1000.0 antes de pasar.

Encontré una forma de hacerlo, tuve que cavar para encontrar las estructuras y funciones correctas. Terminé no usando grados, sino metros en lat y long.

Así es como lo hice:

 -(CLLocationCoordinate2D)translateCoord:(CLLocationCoordinate2D)coord MetersLat:(double)metersLat MetersLong:(double)metersLong{ CLLocationCoordinate2D tempCoord; MKCoordinateRegion tempRegion = MKCoordinateRegionMakeWithDistance(coord, metersLat, metersLong); MKCoordinateSpan tempSpan = tempRegion.span; tempCoord.latitude = coord.latitude + tempSpan.latitudeDelta; tempCoord.longitude = coord.longitude + tempSpan.longitudeDelta; return tempCoord; } 

Y, por supuesto, si realmente necesito usar grados en el futuro, es bastante fácil (creo …) hacer algunos cambios para que funcionen como lo pedí.

Usar una MKCoordinateRegion tiene algunos problemas: la región devuelta se puede ajustar para que quepa, ya que los dos deltas pueden no corresponder exactamente con la proyección en esa latitud, si quieres un delta cero para uno de los ejes, no tienes suerte, etc.

Esta función usa MKMapPoint para realizar traducciones de coordenadas que le permiten mover puntos en el espacio de coordenadas de la proyección del mapa y luego extraer una coordenada de eso.

 CLLocationCoordinate2D MKCoordinateOffsetFromCoordinate(CLLocationCoordinate2D coordinate, CLLocationDistance offsetLatMeters, CLLocationDistance offsetLongMeters) { MKMapPoint offsetPoint = MKMapPointForCoordinate(coordinate); CLLocationDistance metersPerPoint = MKMetersPerMapPointAtLatitude(coordinate.latitude); double latPoints = offsetLatMeters / metersPerPoint; offsetPoint.y += latPoints; double longPoints = offsetLongMeters / metersPerPoint; offsetPoint.x += longPoints; CLLocationCoordinate2D offsetCoordinate = MKCoordinateForMapPoint(offsetPoint); return offsetCoordinate; } 

La respuesta de Nicsoft es fantástica y es exactamente lo que necesitaba. CLLocationCoordinate2D una versión de Swift 3-y que es un poco más conciso y se puede CLLocationCoordinate2D directamente en una instancia de CLLocationCoordinate2D :

 public extension CLLocationCoordinate2D { public func transform(using latitudinalMeters: CLLocationDistance, longitudinalMeters: CLLocationDistance) -> CLLocationCoordinate2D { let region = MKCoordinateRegionMakeWithDistance(self, latitudinalMeters, longitudinalMeters) return CLLocationCoordinate2D(latitude: latitude + region.span.latitudeDelta, longitude: longitude + region.span.longitudeDelta) } }