Realización de la función de agregación basada en Arcgis para iOS 10.2.5

Pon primero la dirección del código: https://github.com/xjf1990930/ArcGis-iOS-Cluster

Antes de que se implemente la agregación, la interfaz de visualización de datos tiene este aspecto:

Antes de la agregación
Efecto de prepolimerización

La acumulación de una cantidad tan grande de datos es, en primer lugar, antiestética y, en segundo lugar, consume rendimiento de visualización, por lo que se presenta una solicitud de visualización agregada. Después de pensar, la idea general es esta: primero divida la pantalla en N partes iguales, una de las cuales corresponde a El rango del mapa en la pantalla actual se usa como la unidad de rango de agregación más pequeña, y luego la consulta espacial se realiza en función de esta unidad de rango de agregación. El número de resultados de la consulta indica el número de números de agregación que se muestran y se pueden marcar en la AGSGraphicLayer con AGSSymbol.

Solo escribe como dices, así que implementé las siguientes cuatro categorías, y los jueces pueden usarlas de inmediato, con muy poca intrusión de código:

WHGIClusterManager: responsable de asociar objetos de mapa AGSMapView y crear objetos de unidad de agregación

WHGIClusterModel: objeto de unidad de agregación, responsable de las tareas de consulta espacial en esta unidad

WHGIClusterTask: cada tarea de consulta (diferentes ID de capa deben realizar AGSQueryTask independiente)

WHGIBlockTask: una clase de gestión de colas

Código de clave de WHGIClusterManager:

//聚合时监听地图缩放和拖拽变化
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mapViewDidEndZoomAction:) name:AGSMapViewDidEndZoomingNotification object:nil];//缩放触发重新聚合查询
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mapViewDidEndDragAction:) name:AGSMapViewDidEndPanningNotification object:nil];//拖拽触发继续聚合查询


//获取当前屏幕范围内的地图需要聚合查询的所有最小单元
- (NSMutableArray *)currentScreenClusterEnvlopes {
    
    NSUInteger cluster_X = 3;//取当前屏幕三分之一宽为聚合最小单元的宽
    NSUInteger cluster_Y = 4;//取当前屏幕四分之一高为聚合最小单元的高
    
    AGSEnvelope *clipTemp = [self.mapView toMapEnvelope:CGRectMake(0, 0, self.mapView.frame.size.width/cluster_X, self.mapView.frame.size.height/cluster_Y)];
    
    AGSEnvelope *currentScreenEnv = [self.mapView toMapEnvelope:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
    
    AGSPoint *startPoint = [AGSPoint pointWithX:self.mapView.maxEnvelope.xmin y:self.mapView.maxEnvelope.ymin spatialReference:self.mapView.spatialReference];
    //参照当前地图最大范围的最小x和y坐标作为原点,计算出当前屏幕地图范围所有的聚合单元
    NSUInteger env_minX = floor((currentScreenEnv.xmin - startPoint.x)/clipTemp.width);
    NSUInteger env_minY = floor((currentScreenEnv.ymin - startPoint.y)/clipTemp.height);
    
    NSMutableArray *allEnvs = [NSMutableArray new];
    AGSEnvelope *tempEnv = nil;
    for (NSUInteger i = 0; i<=cluster_X; i++) {
        for (NSUInteger j = 0; j<=cluster_Y; j++) {
            tempEnv = [[AGSEnvelope alloc] initWithXmin:startPoint.x+(i+env_minX)*clipTemp.width ymin:startPoint.y+(j+env_minY)*clipTemp.height xmax:startPoint.x+(i+1+env_minX)*clipTemp.width ymax:startPoint.y+(j+1+env_minY)*clipTemp.height spatialReference:self.mapView.spatialReference];
            BOOL contains = NO;
            for (WHGIClusterModel *clustModel in self.clusterModels) {
                if ([clustModel.referEnv isEqualToEnvelope:tempEnv]) {
                    contains = YES;
                    break;
                }
            }
            if (!contains) {
                [allEnvs addObject:tempEnv];
            }
        }
    }
    
    return allEnvs;
}

Código de clave WGIClusterModel:

//展示查询的结果,最小聚合单元内大于3个结果,显示聚合数字符号,否则显示原本的符号
- (void)displayClust {
    
    if (self.clusterLayer == nil) {
        return;
    }
    
    NSMutableArray *tempGraphics = [NSMutableArray new];
    
    for (WHGIClusterTask *taskModel in self.tasks) {
        if (!taskModel.marked && taskModel.clustSuccess) {//已经在底图上显示过了就不会再处理一次
            [tempGraphics addObjectsFromArray:taskModel.allResults];
            taskModel.marked = YES;
        }
    }
    
    if (tempGraphics.count<=0) {
        return;
    }
    
    NSArray<AGSGraphic *>* graphics = tempGraphics;
    NSMutableArray<AGSGraphic *>* showGraphics = [NSMutableArray new];
    if (graphics.count>0) {
        if (graphics.count>3) {
            [showGraphics addObject:[AGSGraphic graphicWithGeometry:graphics.firstObject.geometry symbol:[self textSymbol:[NSString stringWithFormat:@"%@",@(graphics.count)]] attributes:nil]];
        }else{
            //小于三个,则每个graphic单独显示
            for (AGSGraphic *singleShowGraphic in graphics) {
                
                for (WHGIClusterTask *taskModel in self.tasks) {
                    if ([taskModel.allResults containsObject:singleShowGraphic]) {
                        [showGraphics addObject:[AGSGraphic graphicWithGeometry:singleShowGraphic.geometry symbol:[self pictureSymbolWithLayerID:taskModel.layerID] attributes:nil]];
                        break;
                    }
                }
            }
        }
        [self.clusterLayer addGraphics:showGraphics];
    }
}

Código de clave WGIClusterTask:

//根据最小聚合单元的范围进行空间查询
- (void)clustWithEnvlope:(AGSEnvelope *)env andCall:(void(^)(BOOL success,NSArray<AGSGraphic *> *allResults))callBack {
    if (nil == self.currentOperation || self.currentOperation.finished) {
        if (self.clustSuccess == NO) {
            self.resultCall = callBack;
            self.queryTask = [[AGSQueryTask alloc] initWithURL:[NSURL URLWithString:[[NSString stringWithFormat:@"%@/%@",pWHGIClustLayerService,self.layerID] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
            AGSQuery *queryObject = [[AGSQuery alloc] init];
            queryObject.geometry = env;
            queryObject.whereClause = @"1=1";
            queryObject.outFields = @[@"*"];
            queryObject.returnGeometry = YES;
            queryObject.outSpatialReference = env.spatialReference;
            queryObject.spatialRelationship = AGSSpatialRelationshipContains;
            self.queryTask.delegate = self;
            self.currentOperation = [self.queryTask executeWithQuery:queryObject];
        }else{
            if (callBack) {
                callBack(YES,self.allResults);
            }
        }
    }else{
        if (callBack) {
            callBack(NO,nil);
        }
    }
}

WHGIBlockTask es una clase de herramienta que puede poner en cola y ejecutar múltiples tareas de devolución de llamada de bloque asincrónico.

También hay algunas optimizaciones detalladas, como la necesidad de finalizar la última tarea inconclusa cuando el usuario hace zoom más rápido, etc., todos los detalles están en el código.

El efecto final es el siguiente:

después de la polimerización
después del efecto de polimerización

 

Supongo que te gusta

Origin blog.csdn.net/qq_31672459/article/details/102947417
Recomendado
Clasificación