Calcular nova coordenada x metros e y graus longe de uma coordenada

Eu devo estar perdendo alguma coisa nos documentos, achei que isso deveria ser fácil …

Se eu tiver uma coordenada e quiser obter uma nova coordenada x metros de distância, em alguma direção. Como eu faço isso?

Eu estou procurando por algo parecido

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

Obrigado!

Infelizmente, não há essa function fornecida na API, então você terá que escrever a sua.

Este site fornece vários cálculos envolvendo latitude / longitude e amostra de código JavaScript. Especificamente, a seção intitulada “Ponto de destino dado distância e rumo do ponto inicial” mostra como calcular o que você está pedindo.

O código JavaScript está na parte inferior da página e aqui está uma maneira possível de convertê-lo em 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; } 

No código JS, ele contém este link que mostra um cálculo mais preciso para distâncias maiores que 1/4 da circunferência da Terra.

Observe também que o código acima aceita a distância em km, portanto, certifique-se de dividir os medidores por 1000,0 antes de passar.

Eu encontrei uma maneira de fazer isso, tive que cavar para encontrar as estruturas e funções corretas. Eu acabei não usando graus mas metros para lat e long em vez disso.

Veja como eu fiz:

 -(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; } 

E, claro, se eu realmente precisar usar graduação no futuro, é bem fácil (eu acho …) fazer algumas alterações acima para que funcione como eu realmente pedi.

Usar um MKCoordinateRegion tem alguns problemas – a região retornada pode ser ajustada para caber, já que os dois deltas podem não mapear exatamente para a projeção nessa latitude, se você quiser zero delta para um dos eixos sem sorte, etc.

Essa function usa o MKMapPoint para executar traduções de coordenadas que permitem mover pontos no espaço de coordenadas da projeção do mapa e extrair uma coordenada a partir disso.

 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; } 

A resposta da Nicsoft é fantástica e exatamente o que eu precisava. Eu criei uma versão Swift 3-y que é um pouco mais concisa e pode ser chamada diretamente em uma instância 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) } }