iOS 利用高德地图WMS服务

 

Demo:  https://github.com/xushiyou23/AMapTesting

转:

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Bear_861110453/article/details/81564605
 
本文主要介绍通过自定义高德地图 MATileOverlay 接口,添加 WMS 服务到地图上。

自定义类 WMSTileOverlayUtil,继承自高德地图接口 MATileOverlay,主要重载函数: 
- (NSURL *)URLForTilePath:(MATileOverlayPath)path; 
- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result;,见代码注释。

#import <Foundation/Foundation.h>
#import <MAMapKit/MATileOverlay.h>


@interface WMSTileOverlayUtil : MATileOverlay

- (id)initWithRootURL:(NSString *)rootRUL;

/**
 * @brief 以tile path生成URL。用于加载tile,此方法默认填充URLTemplate * @param path tile path * @return 以tile path生成tileOverlay */ - (NSURL *)URLForTilePath:(MATileOverlayPath)path; @end
#import "WMSTileOverlayUtil.h"
#import <MAMapKit/MAMapKit.h>
#import <AMapFoundationKit/AMapFoundationKit.h>
#import <math.h> #import "Api.h" @implementation WMSTileOverlayUtil { NSString * rootURL; NSInteger titleSize; // = 256 double initialResolution; // = 156543.03392804062;//2*Math.PI*6378137/titleSize; double originShift; // = 20037508.342789244;//2*Math.PI*6378137/2.0; 周长的一半 double HALF_PI; // = Math.PI / 2.0; double RAD_PER_DEGREE; // = Math.PI / 180.0; double METER_PER_DEGREE; // = originShift / 180.0;//一度多少米 double DEGREE_PER_METER; // = 180.0 / originShift;//一米多少度 } - (id)initWithRootURL:(NSString *)rootRUL { self = [super init]; if (self) { rootURL = rootRUL; titleSize = 256; initialResolution = 156543.03392804062; originShift = 20037508.342789244; HALF_PI = M_PI_2; RAD_PER_DEGREE = M_PI / 180.0; METER_PER_DEGREE = originShift / 180.0; DEGREE_PER_METER = 180.0 / originShift; } return self; } /** * @brief 以tile path生成URL。用于加载tile,此方法默认填充URLTemplate * @param path tile path * @return 以tile path生成tileOverlay */ - (NSURL *)URLForTilePath:(MATileOverlayPath)path { NSString * strURL = [[NSString alloc] initWithFormat:@"%@%@", rootURL, [self titleBoundsByX:path.x Y:path.y Z:path.z]]; NSURL * url = [NSURL URLWithString:strURL]; return url; } /** * @brief 加载被请求的tile,并以tile数据或加载tile失败error访问回调block;默认实现为首先用URLForTilePath去获取URL,然后用异步NSURLConnection加载tile * @param path tile path * @param result 用来传入tile数据或加载tile失败的error访问的回调block */ - (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result { if (path.z < 8) return; NSURL * url = [self URLForTilePath:path]; NSString * strURL = url.absoluteString; SuccessCallback successCallback = ^(id responseObject) { UIImage * image = [UIImage imageWithData:responseObject]; NSData * data = UIImagePNGRepresentation(image); result(data, nil); }; FailureCallBack failureCallBack = ^(NSError *error) { result(nil, error); }; [Api GETWMSWith:strURL successCallback:successCallback failureCallBack:failureCallBack]; } /** * @brief 取消请求瓦片,当地图显示区域发生变化时,会取消显示区域外的瓦片的下载, 当disableOffScreenTileLoading=YES时会被调用。since 5.3.0 * @param path tile path */ - (void)cancelLoadOfTileAtPath:(MATileOverlayPath)path { [super cancelLoadOfTileAtPath:path]; } /** * 根据瓦片的x/y等级返回瓦片范围 * * @param tx x * @param ty y * @param zoom z * @return url */ - (NSString *)titleBoundsByX:(NSInteger)tx Y:(NSInteger)ty Z:(NSInteger)zoom { double minX = [self pixels2Meters:(tx * titleSize) zoom:zoom]; double maxY = -[self pixels2Meters:(ty * titleSize) zoom:zoom]; double maxX = [self pixels2Meters:((tx + 1) * titleSize) zoom:zoom]; double minY = -[self pixels2Meters:((ty + 1) * titleSize) zoom:zoom]; //转换成经纬度 minX = [self meters2Lon:minX]; minY = [self meters2Lat:minY]; maxX = [self meters2Lon:maxX]; maxY = [self meters2Lat:maxY]; //坐标转换工具类构造方法 Gps( WGS-84) 转 为高德地图需要的坐标 CLLocationCoordinate2D amapcoord = AMapCoordinateConvert(CLLocationCoordinate2DMake(minY, minX), AMapCoordinateTypeGPS); minY = amapcoord.latitude; minX = amapcoord.longitude; CLLocationCoordinate2D maxAmapcoord = AMapCoordinateConvert(CLLocationCoordinate2DMake(maxY, maxX), AMapCoordinateTypeGPS); maxY = maxAmapcoord.latitude; maxX = maxAmapcoord.longitude; NSString * result = [[NSString alloc] initWithFormat:@"%f,%f,%f,%f&width=256&height=256", minX, minY, maxX, maxY]; return result; } /** * 根据像素、等级算出坐标 * * @param p p * @param zoom z * @return double */ - (double)pixels2Meters:(NSInteger)p zoom:(NSInteger)zoom { return p * [self resolution:zoom] - originShift; } /** * 计算分辨率 * * @param zoom z * @return double */ - (double)resolution:(NSInteger)zoom { return initialResolution / (pow(2, zoom)); } /** * X米转经纬度 */ - (double)meters2Lon:(double)mx { double lon = mx * DEGREE_PER_METER; return lon; } /** * Y米转经纬度 */ - (double)meters2Lat:(double)my { double lat = my * DEGREE_PER_METER; lat = 180.0 / M_PI * (2 * atan(exp(lat * RAD_PER_DEGREE)) - HALF_PI); return lat; } @end

 

其中,- (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result; 函数中,使用自己写的 网络访问层去请求 wms 服务,并通过 result 函数贴到地图上。你也可以 改写成自己的网络访问层。

问题

为啥要重载 - (void)loadTileAtPath:(MATileOverlayPath)path result:(void (^)(NSData *tileData, NSError *error))result; 函数,因为只是从载 - (NSURL *)URLForTilePath:(MATileOverlayPath)path; 生成 NSURL 后,loadTileAtPath 函数会去通过网络请求加载 wms 服务,然而,这一步网络请求会报错:NSURLConnection -errorcode -1004,且一个星期没有解决为啥报错,所以只得重写,如果有熟悉高德地图 api 的小伙伴能够给予解答,不胜感激。

注意

如果使用 AFNetworking 要注意修改支持的类型:

 AFHTTPSessionManager * manager = [[AFHTTPSessionManager alloc] init];
 AFHTTPResponseSerializer *serializer=[AFHTTPResponseSerializer serializer];
 serializer.acceptableContentTypes = [NSSet setWithObject:@"image/png"]; manager.responseSerializer = serializer;

转载于:https://www.cnblogs.com/xujiahui/p/9600588.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值