IOS Location Manager 위치 지정 국내 오프셋, 화성 좌표(GCJ-02) 솔루션
5690 단어 Objective-CIOS
CLLocation Manager 클래스는 위치의 경위를 실시간으로 확인할 수 있으며 경위를 통해 MapView에 위치를 지정할 수 있습니다.
// CLLocationManager
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
//
[locationManager setDelegate:self];
// CLLocationManager
[locationManager setDistanceFilter:kCLDistanceFilterNone];
// CLLocationManager
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
// CLLocationManager ,
[locationManager startUpdatingLocation];
아래 CLLocation Manager의 위도를 위임하거나 업데이트하여 MapView에 표시할 수 있습니다
//CLLocationManager
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
// newLocation
CLLocation *loc = [locations objectAtIndex:0];
}
그러나 국내 지도의 경우 LocationManager로 위치를 정하면 비교적 큰 거리가 있다
편향했어
왜 이러지??요 며칠 동안 이 분야의 자료를 계속 찾았는데 각종 구글,baidu 포럼에서 제시한 답도 각각 다르다.
와이파이 핫스팟 기지국 gps 등으로 인한 문제점이 있었는데 결국 찾아냈습니다. 원래 국내 지도에서 사용하는 좌표 시스템은
GCJ-02와 iossdk에서 사용하는 것은 국제 표준의 좌표 시스템이다
WGS-84.
국내에서는 암호화된 좌표계 GCJ-02가 인터넷상에서 부르는 화성 좌표이기 때문이다.
위치 관리자는 화성 좌표가 이동한 후의 경위도를 얻었기 때문에 맵뷰에서 큰 편차가 생겼고 MK맵뷰에서 자신의 위치를 포지셔닝함으로써 얻은 경위도는 정확하다. 앱이 국내 지도에 대한 편향 최적화를 했기 때문이다.1、그러면 임시적인 해결 방법: 자신의 정확한 경위도를 얻으려면 MKMapView에서 자신의 위치를 직접 찾으면 된다.
// MKMapView setShowUserLocation:YES
[self.mapView setShowsUserLocation:YES];
// MKMapView
[self.mapView setHidden:YES];
그런 다음 MKMapView 위임 방법을 사용하여 정확한 경위도를 얻을 수 있습니다.
-(void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
CLLocationCoordinate2D coord = [userLocation coordinate];
NSLog(@" :%f, :%f",coord.latitude,coord.longitude);
}
이 방법은 간단하지만 실시간으로 자신의 위치를 얻을 수 있고 기본적으로 정확한 위치이지만 locationManager의 일부 기능을 사용할 수 없다.
그렇다면 화성 좌표에서locationManager를 사용하여 정확한 위치를 얻을 수 있는 더 좋은 해법은 없을까요?몇 편의 블로그를 보면 비슷한 답이 나온다. 바로 앱의 개인 모듈 클래스에서 얻은 방법을 호출하여 경위도에 대한 편향 수정을 하는 것이다.
http://blog.csdn.net/zhibudefeng/article/details/8495837
http://yach.me/blog/2011/11/09/huo-xing-zuo-biao-xi-wen-ti-zai-iosxia-de-xiu/
위 두 문장 모두 앱의 개인 모듈인 MKLocation Manager를 사용해 오프셋을 수정하는 것을 언급했지만 안타깝게도 개인 모듈을 사용하면 앱스토어 심사에 실패할 수 있지만 다행히도 이런 방식은 IOS5 이전 시스템에서만 사용할 수 있다...적어도 오늘 우리는 이 방식을 사용해야 할지 말아야 할지 걱정할 필요가 없다.
다음은 본론입니다. 마지막으로android의 화성 좌표 변환 알고리즘을 찾았습니다. 그리고 다음과 같이 고쳤습니다.
WGS-84 좌표 시스템이 GCJ-02의 Objective-C 코드로 바뀌면 CLLocation Manager라는 종류를 편리하게 사용할 수 있다.
2. WGS-84를 GCJ-02(화성 좌표)로 변환:
새 클래스 "WGS84TOGCJ02"를 만듭니다.h헤드 파일에 정의된 내용:
4
// Copyright (c) 2013 swinglife. All rights reserved.
//
#import
#import
@interface WGS84TOGCJ02 : NSObject
//
+(BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location;
// GCJ-02
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc;
@end
WGS84TOGCJ02.m 파일:// Copyright (c) 2013 swinglife. All rights reserved.
//
#import "WGS84TOGCJ02.h"
const double a = 6378245.0;
const double ee = 0.00669342162296594323;
const double pi = 3.14159265358979324;
@implementation WGS84TOGCJ02
+(CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc
{
CLLocationCoordinate2D adjustLoc;
if([self isLocationOutOfChina:wgsLoc]){
adjustLoc = wgsLoc;
}else{
double adjustLat = [self transformLatWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double adjustLon = [self transformLonWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double radLat = wgsLoc.latitude / 180.0 * pi;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = sqrt(magic);
adjustLat = (adjustLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
adjustLon = (adjustLon * 180.0) / (a / sqrtMagic * cos(radLat) * pi);
adjustLoc.latitude = wgsLoc.latitude + adjustLat;
adjustLoc.longitude = wgsLoc.longitude + adjustLon;
}
return adjustLoc;
}
//
+(BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location
{
if (location.longitude < 72.004 || location.longitude > 137.8347 || location.latitude < 0.8293 || location.latitude > 55.8271)
return YES;
return NO;
}
+(double)transformLatWithX:(double)x withY:(double)y
{
double lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(abs(x));
lat += (20.0 * sin(6.0 * x * pi) + 20.0 *sin(2.0 * x * pi)) * 2.0 / 3.0;
lat += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0;
lat += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0;
return lat;
}
+(double)transformLonWithX:(double)x withY:(double)y
{
double lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(abs(x));
lon += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
lon += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0;
lon += (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0;
return lon;
}
@end
마지막으로 isLocation OutOfChina를 판단하고transformLatWithX 방법을 사용하면 변환된 CLLocation Coordinate2D 구조 유형을 얻을 수 있습니다
//CLLocationManager
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{
// newLocation
CLLocation *loc = [locations objectAtIndex:0];
//
if (![WGS84TOGCJ02 isLocationOutOfChina:[loc coordinate]]) {
// coord
CLLocationCoordinate2D coord = [WGS84TOGCJ02 transformFromWGSToGCJ:[loc coordinate]];
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
PreferenceBundle에서 오른쪽 상단에 Respring 버튼을 클릭합니다.만나서 반갑습니다, Minazuki라고합니다. 프로필 이름 : Minazuki_dev Twitter : Repo : 아직 중학생이므로 말이 이상한 곳이 있습니다만 용서해 주세요… 🙏 theos (Mac이든 단품이든 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.