2011-07-09 8 views
29

Debo estar perdiendo somthing a cabo en la documentación, pensé que esto debe ser fácil ...Calcular nueva coordenada x e y grado metros de distancia de una coordenada

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

estoy en busca de algo así como

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

Gracias!

Respuesta

29

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

This site ofrece varios cálculos que implican 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 está en la parte inferior de esa página y aquí es una forma posible para convertirlo en 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 this link que muestra un cálculo más preciso para distancias más de 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.

+0

Gracias por su respuesta! En realidad, encontré la manera de hacerlo. Ver mi propia respuesta. – Nicsoft

+0

Buena respuesta, me gusta porque trata directamente con las coordenadas y más completamente responde la pregunta ya que toma en cuenta la dirección. – johnrechd

12

Encontré una forma de hacerlo, tuve que excavar 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 necesita usar grados en el futuro, que es bastante fácil (creo ...) para hacer algunos cambios para arriba para obtener para que funcione como realmente pedí.

+0

simple y eficaz para mis necesidades. ¡Gracias! –

+1

Entonces, ¿cómo terminas manejando los títulos? –

5

El uso de un MKCoordinateRegion tiene algunos problemas: la región devuelta se puede ajustar para caber ya que los dos deltas pueden no corresponder exactamente con la proyección en esa latitud, si quiere delta cero para uno de los ejes no tiene 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; 
} 
+0

Esta respuesta funcionó muy bien para mí y me permitió convertir una MapItem.placemark.region (que era unaCircularRegion; tiene un radio dado en metros) en una región de recuadro delimitador –

4

La respuesta de Nicsoft es fantástica y es exactamente lo que necesitaba. He creado un Swift 3-y versión que es un poco más concisa y puede ser llamado directamente en una instancia 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) 
    } 

} 
+4

Podría llamarse mejor 'translate' ya que técnicamente es una traducción, no una transformación. –

Cuestiones relacionadas