Подтвердить что ты не робот

Вычислите новую координату x метров и y градус от одной координаты

Мне нужно пропустить что-то в документах, я думал, что это должно быть легко...

Если у меня есть одна координата и вы хотите получить новую координату на расстоянии х метров, в определенном направлении. Как это сделать?

Я ищу что-то вроде

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

Спасибо!

4b9b3361

Ответ 1

К сожалению, в API нет такой функции, поэтому вам придется писать свои собственные.

Этот сайт дает несколько вычислений с использованием широты/долготы и примера кода JavaScript. В частности, раздел "Точка назначения с заданным расстоянием и опорой от начальной точки" показывает, как рассчитать то, что вы просите.

Код JavaScript находится внизу этой страницы, и здесь возможен один из способов конвертировать его в 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 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;
}

В коде JS он содержит эту ссылку, которая показывает более точный расчет расстояний, превышающих 1/4 окружности Земли.

Также обратите внимание, что приведенный выше код принимает расстояние в км, поэтому перед прохождением делитесь метрами на 1000,0.

Ответ 2

Я нашел один способ сделать это, пришлось копать, чтобы найти правильные структуры и функции. Я закончил тем, что не использовал градусы, но метры для lat и long вместо этого.

Вот как я это сделал:

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

}

И, конечно, если мне действительно нужно использовать градусы в будущем, это довольно легко (я думаю...), чтобы сделать некоторые изменения выше, чтобы заставить его работать, как я действительно просил.

Ответ 3

Использование MKCoordinateRegion имеет некоторые проблемы - возвращенная область может быть скорректирована, чтобы соответствовать, поскольку две дельты не могут точно отображать проекцию на этой широте, если вы хотите, чтобы нулевая дельта для одной из осей вы не повезло и т.д.

Эта функция использует MKMapPoint для выполнения координат, которые позволяют перемещать точки в координатном пространстве проекции карты, а затем извлекать из нее координату.

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

Ответ 4

Ответ Nicsoft фантастический и именно то, что мне нужно. Я создал версию Swift 3-y, которая немного более кратким и может быть вызвана непосредственно на экземпляр 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)
  }

}