美文网首页ArcGIS学习
ArcGIS for IOS 使用和集成(二)

ArcGIS for IOS 使用和集成(二)

作者: 多喝热开水 | 来源:发表于2020-03-31 10:58 被阅读0次

加载底图图层与信息图层

在第一章中讲述了如果集成ArcGIS ,本章我们来讲如何使用ArcGIS 如何加载底图,在底图上加载定位图层等等

初始化 AGSMapView 加载底图图层

为了让AGSMapView的业务逻辑更加清晰 我们选择新建一个ArcGISMapView 继承 AGSMapView ,将所有的关于Layer方面的操作都写在 ArcGISMapView 中,以减轻VC的业务压力。

先看下项目目录:

FB04C7F0-1761-443D-ABF9-C81B3C5E3E33.png

在ArcGISMapView.h文件中:

@interface ArcGISMapView : AGSMapView
/// 基础图层
@property (nonatomic, strong) AGSTiledMapServiceLayer *baseMapLayer;

/// 初始化页面
/// @param baseURL 底图地址
- (instancetype)initWithFrame:(CGRect)frame BaseURL:(NSString *)baseURL;

/// 设置基础底图图层
/// @param baseURL 底图地址
- (void) setupMapBaseLayerWithURL:(NSString *)baseURL;

@end

在ArcGISMapView.m文件中:

 @implementation ArcGISMapView

- (instancetype)initWithFrame:(CGRect)frame BaseURL:(NSString *)baseURL
{
    self = [super initWithFrame:frame];
    
    if (self) {
        [self setupMapBaseLayerWithURL:baseURL];
    }
    return self;
}

- (void) setupMapBaseLayerWithURL:(NSString *)baseURL
{
    NSURL *baseMapURL = [NSURL URLWithString:baseURL];
    AGSTiledMapServiceLayer *baseMapLayer = [AGSTiledMapServiceLayer tiledMapServiceLayerWithURL:baseMapURL];
    self.baseMapLayer = baseMapLayer;
    
    // 插入底图
    [self insertMapLayer:baseMapLayer withName:MAP_BASE_NAME atIndex:0];
}

新建VC ArcGISMapViewController ,在VC中我们将mapView初始化

@interface ArcGISMapViewController ()<AGSMapViewLayerDelegate>

@property (nonatomic, strong) ArcGISMapView *mapView;

@end

@implementation ArcGISMapViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    [self.view addSubview:self.mapView];
}

#pragma mark - AGSMapViewLayerDelegate

- (void)mapViewDidLoad:(AGSMapView *)mapView
{
    NSLog(@"mapView did load");
    
}

#pragma mark - init function

- (ArcGISMapView *)mapView
{
    if (!_mapView) {
        _mapView = [[ArcGISMapView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) BaseURL:@"输入你的底图地址"];
        _mapView.layerDelegate = self;
    }
    return _mapView;
}

@end

通过上面的代码即能看到底图被正常的加载到了页面中:


IMG_6129.PNG

开启地图自动定位到当前位置并显示周边

具体效果如如所示


IMG_6130.PNG

ArcGIS 与百度地图API还是有很多的不同的,在百度地图里你可能只需要使用BMKUserLocation 这个类就可以轻松展示定位,在ArcGIS中,你需要对AGSMapView 添加指定的图层(Layer) 才可以展示这种定位效果。

我们新创建类 ArcGISLocationLayer 继承 AGSGraphicsLayer , 需要在这个图层上绘制我们需要的定位效果
在 ArcGISLocationLayer.h文件中:

@interface ArcGISLocationLayer : AGSGraphicsLayer
/// 初始化定位图层
- (instancetype) initLocationLayer;

/// 更新定位
/// @param lat 纬度
/// @param lon 经度
/// @param radius 区域范围 (米)
- (void) updateLocationWithLat:(double)lat Lon:(double)lon radius:(double) radius;

@end

在 ArcGISLocationLayer.m文件中:

@interface ArcGISLocationLayer()

@property (strong, nonatomic )AGSGraphic *locationGraphic;

@property (strong, nonatomic )AGSGraphic *locationCircleGraphic;

@end

@implementation ArcGISLocationLayer

- (instancetype) initLocationLayer
{
    self = [ArcGISLocationLayer graphicsLayer];
    
    if (self ) {
        
        // 增加定位区域
        [self addGraphic:self.locationGraphic];
        // 添加环形显示区域
        [self addGraphic:self.locationCircleGraphic];
    }
    
    return self;
}

- (void) updateLocationWithLat:(double)lat Lon:(double)lon radius:(double) radius
{
   // 当需要展示定位时,让其正常在地图中展示
    self.locationCircleGraphic.visible = YES;
    self.locationGraphic.visible = YES;
    
    AGSPoint *point=[AGSPoint pointWithX:lon y:lat spatialReference:self.mapView.spatialReference];
    
    AGSGeometryEngine *geoEng=[AGSGeometryEngine defaultGeometryEngine];
    AGSPolygon *geBuffer = [geoEng bufferGeometry:point byDistance:[ArcGISCommonToolKit getLocationRadius:radius Lon:point.x Lat:point.y]];
    
    self.locationCircleGraphic.geometry = geBuffer;
    self.locationGraphic.geometry = point;
    
    [self refresh];
}

#pragma mark - init function
- (AGSGraphic *)locationGraphic
{
    if (!_locationGraphic) {
        // 初始化一个(0,0)
        AGSPoint *point=[AGSPoint pointWithX:0 y:0 spatialReference:self.mapView.spatialReference];
        
        // 设置定位到当前的icon样式
        AGSPictureMarkerSymbol *markerSymbol = [[AGSPictureMarkerSymbol alloc] initWithImageNamed:@"gis_location_marker"];
        _locationGraphic = [[AGSGraphic alloc] initWithGeometry:point symbol:markerSymbol attributes:nil];
        
        // 暂时隐藏起来
        _locationGraphic.visible = NO;
    }
    return _locationGraphic;
}

- (AGSGraphic *)locationCircleGraphic
{
    if (!_locationCircleGraphic) {
        
        // 初始化一个(0,0)
        AGSPoint *point = [AGSPoint pointWithX:0 y:0 spatialReference:self.mapView.spatialReference];
        
        AGSGeometryEngine *geoEng = [AGSGeometryEngine defaultGeometryEngine];
        
        // 设置定位环周边的距离与颜色 
        AGSPolygon *geBuffer = [geoEng bufferGeometry:point byDistance:[ArcGISCommonToolKit getLocationRadius:200 Lon:point.x Lat:point.y]];

        AGSSimpleFillSymbol *outerSymbol = [AGSSimpleFillSymbol simpleFillSymbol];
        outerSymbol.color = [[UIColor blueColor] colorWithAlphaComponent:0.1];
        outerSymbol.outline.color = [[UIColor blueColor] colorWithAlphaComponent:0.5];
        _locationCircleGraphic = [[AGSGraphic alloc] initWithGeometry:geBuffer symbol:outerSymbol attributes:nil];
        
        // 暂时隐藏起来
        _locationCircleGraphic.visible = NO;
    }
    return _locationCircleGraphic;
}

@end

绘制的图层中有两层 Graphic :
locationGraphic 展示当前位置icon
locationCircleGraphic 展示周边区域范围圈
需要注意的是展示区域里的Distance(-(AGSMutablePolygon)bufferGeometry:(AGSGeometry)geometry byDistance:(double)distance; 这个方法)是根据当前的底图的 geometry's spatial reference 来判断的距离的,所以有 在墨卡托(Mercator)坐标系下,直接可以输入米,但是在经纬度制下需要我们做下转换,我们在这里简单转换一下就可以了,后面我们会详细讲解坐标值的转换问题。
定义一个新类:ArcGISCommonToolKit 继承NSObject,

+(double)getLocationRadius:(double)radius Lon:(double)lon Lat:(double)lat
{
    return fabs(radius/111000*cos(lat));
}

在ArcGISMapView中我们简单调用下locationLayer里的方法就可以了,记得初始化一下ArcGISLocationLayer,并把该Layer添加到地图中,直接通过:addMapLayer: 方法就可以了

在ArcGISMapViewController 中我们使用系统的CLLocationManager 来获取到当前的位置,传给 ArcGISMapView (我们定义的mapView)直接使用就可以了:

#pragma mark 定位成功后则执行此代理方法
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations
{
    [self.locationmanager stopUpdatingHeading];
    //旧址
    CLLocation *currentLocation = [locations lastObject];
    CLGeocoder *geoCoder = [[CLGeocoder alloc]init];
    //打印当前的经度与纬度
    NSLog(@"%f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude);
    
    double log = 106.66141382;
    double lat = 29.87969803;
    
    [self.mapView updateLocationWithLat:lat Lon:log radius:300 isZoomMap:YES];
}

相关文章

网友评论

    本文标题:ArcGIS for IOS 使用和集成(二)

    本文链接:https://www.haomeiwen.com/subject/bhhbuhtx.html