2011-07-09 7 views
29

I musi być brakuje somthing w docs, myślałem, że to powinno być łatwe ...Oblicz nowy współrzędna x metrów i stopień y od jednego koordynować

Jeśli mam jedną współrzędnych i chcesz dostać nowy koordynować x metry dalej, w pewnym kierunku. Jak mam to zrobic?

szukam czegoś jak

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

Dzięki!

Odpowiedz

29

Niestety, w API nie ma takiej funkcji, więc musisz napisać własną.

This site podaje kilka obliczeń dotyczących długości/szerokości geograficznej i przykładowego kodu JavaScript. W szczególności sekcja zatytułowana "Punkt docelowy podana odległość i namiar od punktu początkowego" pokazuje, jak obliczyć, o co prosisz.

Kod JavaScript jest na dole tej strony i oto jeden z możliwych sposobów, aby przekształcić go do 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; 
} 

W kodzie JS, zawiera ona this link który pokazuje bardziej dokładne obliczenia dla odległościach większa niż 1/4 obwodu Ziemi.

Należy również zwrócić uwagę, że powyższy kod akceptuje odległość w km, dlatego przed przejściem należy podzielić metry na 1000,0.

+0

Dziękuję Ci odpowiedzieć! Właściwie to znalazłem sposób na zrobienie tego. Zobacz moją własną odpowiedź. – Nicsoft

+0

Dobra odpowiedź, podoba mi się ta, ponieważ zajmuje się bezpośrednio współrzędnymi i bardziej kompletnie odpowiada na pytanie, ponieważ bierze pod uwagę kierunek. – johnrechd

12

Znalazłem jeden sposób, aby to zrobić, musiał wykopać, aby znaleźć odpowiednie struktury i funkcje. W końcu nie używałem stopni, ale metrów zamiast lat.

Oto jak to zrobiłem:

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

} 

I oczywiście, jeśli naprawdę trzeba używać stopni w przyszłości, to całkiem proste (chyba ...), aby zrobić kilka zmian powyżej, aby uzyskać to działa tak, jak ja naprawdę prosiłem.

+0

proste i skuteczne dla moich potrzeb. Dzięki! –

+1

Więc jak kończysz dostosowywać stopnie? –

5

Korzystanie z MKCoordinateRegion ma pewne problemy - zwrócony region można dopasować tak, aby pasował, ponieważ dwa delty mogą nie być dokładnie odwzorowane na projekcję na tej szerokości geograficznej, jeśli chcesz uzyskać zerową różnicę dla jednej z osi, w których masz pecha, itp.

Ta funkcja używa MKMapPoint do wykonywania tłumaczeń współrzędnych, co pozwala przesuwać punkty w przestrzeni współrzędnych rzutowanej mapy, a następnie wyodrębnić z niej współrzędną.

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

Ta odpowiedź zadziałała dobrze i pozwoliła mi przekonwertować znak MapItem.pl.region (który był CLCircularRegion, ma promień podany w metrach) w obwiedni regionu regionu –

4

Odpowiedź Nicsoftu jest fantastyczna i dokładnie to, czego potrzebowałem. Utworzyłem Swift 3-y wersję, która jest nieco bardziej zwięzłe i mogą być wywołane bezpośrednio na instancji 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

Może być lepiej nazwany "translate", ponieważ jest to technicznie tłumaczenie, a nie transformacja. –

Powiązane problemy