arcgis api for js学习-QueryStatistics

QueryStatistics


前言

      QueryTask可以用于属性查询和空间查询,一次性只能查询一个图层,但是也可以对空间参考完全相同的一个地图中的图层各自建立查询任务进而实现查询多个图层。
      本文章中涉及到了要素查询FeatureLayer中的一个查询方法queryFeatures(),该方法具体说明请看官方API
      本文选取的代码来自官方实例,在本实例中,实现了对一个图层中的字段查询,方式是:用户使用鼠标点击地图,在地图中会生成一个点图形,和一个缓冲区图形(缓冲区图形仅仅是为了显示观看而已,并不能决定查询的范围,决定查询的范围实际上还是由Query中设置的参数决定的。),查询的结果是在点击地图的位置处,1km范围内总共的斑块数量,各个人口密度的值的平均值、最大值、最小值、标准差。
      比较重要的是:此示例使用的SQL表达式从托管功能服务查询摘要统计信息。可以从任何服务的平均值、最小值、最大值等统计值中生成。但是,SQL表达式仅在advancedQueryCapabilities.supportsSqlExpression is true.的feature services上的查询统计操作中受支持。其中的advancedQueryCapabilities.supportsSqlExpression is true是FeatureLayer的属性。


一、根据人口和面积字段计算人口密度

根据人口和面积计算人口密度就是用人口除以面积,不过地图服务中的shp中的面积字段单位是平方米,所以需要转换,使用人口除以(面积乘以0.000001)得到1km的人口密度,(官方使用的是1英里的人口密度),这样就不用在shp中添加字段计算。

var map = new Map("map", {
                basemap: "streets-night-vector",
                center: [-122.304568, 47.608492],
                zoom: 13
            });
            //要素服务的url
            var url = "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Puget_Sound_BG_Food/FeatureServer/0";

            /******************************************************************
             *
             * The fields used to query for statistics
             * ALAND is land area in square meters 面积
             * TOTPOP_CY is total population in the block group (2015) 人口数量
             * HasData indicates if data is available in the feature
             *
             *******************************************************************/

            var fields = [ "ALAND", "TOTPOP_CY", "HasData", "TOTHH" ];

            // 要素图层
            var blockGroupsLyr = new FeatureLayer(url, {
                outFields: fields
            });
            /******************************************************************
             *
             * The sqlExpression is a standard SQL expression that will be used to
             * query the service for statistics. Since the ALAND field represents the
             * land area in square meters, we want to convert the units to square
             * miles. Therefore `(ALAND * 0.0000003861)` will return the area in square
             * miles. Dividing the TOTPOP_CY by that expression will return the
             * population per square mile.
             *
             * This expression is then set on the onStatisticField property of each
             * statistic definition object. Since we don't have a field for population
             * density in people per square mile, we can use this simple SQL expression
             * in the place of a field and we'll get our desired result:
             *
             * "TOTPOP_CY / (ALAND * 0.0000003861)"
             *
             *******************************************************************/
                //SQL表达式只支持要素服务人口除以面积得到人口密度(我改成算一公里内的人口密度)
            var sqlExpression = "TOTPOP_CY / (ALAND * 0.000001)";

二、创建统计对象StatisticDefinition

其中包括:最小值:minStatDef、最大值:maxStatDef、均值:avgStatDef、标准差:stddevStatDef、计数:countStatDef。
代码如下(示例):

// Object used to request the smallest population density from the
            // block groups within one mile of the mouse click.
            var minStatDef = new StatisticDefinition();
            // 统计类型
            minStatDef.statisticType = "min";
            //将对其计算统计信息的字段名或标准SQL表达式
            minStatDef.onStatisticField = sqlExpression;
            //指定输出字段名
            minStatDef.outStatisticFieldName = "minPopDensity";

            // Object used to request the largest population density from the
            // block groups within one mile of the mouse click.
            var maxStatDef = new StatisticDefinition();
            maxStatDef.statisticType = "max";
            maxStatDef.onStatisticField = sqlExpression;
            maxStatDef.outStatisticFieldName = "maxPopDensity";

            // Object used to request the average population density for
            // all block groups within one mile of the mouse click.
            var avgStatDef = new StatisticDefinition();
            avgStatDef.statisticType = "avg";
            avgStatDef.onStatisticField = sqlExpression;
            avgStatDef.outStatisticFieldName = "avgPopDensity";

            // Object used to request the number of
            // block groups within one mile of the mouse click.
            var countStatDef = new StatisticDefinition();
            countStatDef.statisticType = "count";
            countStatDef.onStatisticField = sqlExpression;
            countStatDef.outStatisticFieldName = "numBlockGroups";

            // Object used to request the standard deviation of the population density for
            // all block groups within one mile of the mouse click.
            var stddevStatDef = new StatisticDefinition();
            stddevStatDef.statisticType = "stddev";
            stddevStatDef.onStatisticField = sqlExpression;
            stddevStatDef.outStatisticFieldName = "StdDevPopDensity";

三、设置参数Query

      其中包括查询的缓冲半径:distance距离+units单位、输出的字段outFields,统计字段:outStatistics 。
注意:这里设置的缓冲区才是真正查询时使用的缓冲区进行的空间过滤(spatial filter)

// Set the base parameters for the query. All statistic definition objects
            // are passed as an array into the outStatistics param
            //查询参数
            var queryParams = new Query();
            //控制
            queryParams.distance = 2;  // Return all block groups within one mile of the point
            queryParams.units = "kilometers";
            queryParams.outFields = fields;
            //统计字段
            queryParams.outStatistics = [minStatDef, maxStatDef, avgStatDef, countStatDef, stddevStatDef];

四、执行查询并渲染结果

      执行查询使用的是FeatureLayer中的方法queryFeatures。本文通过设置变更上面Query的查询参数,观察查询到的结果1.不设置查询的统计字段,2.变更查询的缓冲区,或者不设置缓冲区,3.变更查询的空间关系。借助几种情况观察得到参数的具体含义
      在下面的代码中需要注意的是:在点击地图的时候还设置了一个查询参数queryParams.geometry = point;,这个参数使用来空间过滤的,使用这个点击的点会相应的使前面设置的缓冲区依据该点生成缓冲区,这个参数会和空间关系spatialRelationship一起使用,如果不指定spatialRelationship该查询参数,Query会使用其中的默认参数Query.SPATIAL_REL_INTERSECTS;是指一个要素一部分包含在另外一个要素中的空间关系。

// Executes on each map click
            function getPoint(evt){

                // Set the location of the mouse click event to the query parameters
                //点击的点
                var point = evt.mapPoint;
                //空间过滤条件(空间关系),如果只设置了geometry,未设置spatialRelationship,spatialRelationship有一个默认值是Query.SPATIAL_REL_INTERSECTS
                queryParams.geometry = point;
                // queryParams.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;

                // Clear the graphics from any previous queries
                map.graphics.clear();

                // Add a point graphic represting the location clicked on the map
                var ptGraphic = new Graphic(point, pointSymbol);
                map.graphics.add(ptGraphic);//画了一个点击点

                // Add a graphic representing a one-mile buffer around the clicked point
                var buffer = geometryEngine.geodesicBuffer(point, 1, "kilometers");//投影是wgs1984或者web墨卡托就使用这个,否则就是用buffer()
                var bufferGraphic = new Graphic(buffer, buffSymbol);
                map.graphics.add(bufferGraphic);//在点击点的位置画了一个buffer

                // Execute the statistics query against the feature service and call the getStats() callback
                blockGroupsLyr.queryFeatures(queryParams, getStats, errback);
            }

            // Executes on each query
            function getStats(results){
            //通过设置变更上面的参数,观察查询到的结果1.不设置查询的统计字段,2.变更查询的缓冲区,或者不设置缓冲区,3.变更查询的空间关系。借助几种情况观察得到参数的具体意思
                console.log(results);
                var graphics = results.features;
                for (var i = 0; i < graphics.length; i++) {
                    console.log(graphics[i]);
                    var graphic = graphics[i];
                    graphic.setSymbol(fill);
                    map.graphics.add(graphic);
                }

                // The return object of the query containing the statistics requested
                var stats = results.features[0].attributes;

                // Print the statistic results to the DOM
                dom.byId("countResult").innerHTML = Math.round(stats.numBlockGroups);
                dom.byId("minResult").innerHTML = Math.round(stats.minPopDensity) + " people/sq mi";
                dom.byId("maxResult").innerHTML = Math.round(stats.maxPopDensity) + " people/sq mi";
                dom.byId("avgResult").innerHTML = Math.round(stats.avgPopDensity) + " people/sq mi";
                dom.byId("stdDevResult").innerHTML = Math.round(stats.StdDevPopDensity) + " people/sq mi";
            }

全部代码:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
    <title>Query Statistics with SQL Expression</title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.34/esri/css/esri.css">
    <style>
        html, body, #map {
            height: 100%;
            width: 100%;
            margin: 0;
            padding: 0;
        }
        #results {
            position: absolute;
            z-index: 10;
            bottom: 45px;
            right: 10px;
            background-color: black;
            opacity: 0.8;
            color: cornsilk;
            width: 300px;
            padding: 5px;
            padding-bottom: 10px;
            padding-left: 10px;
            padding-right: 10px;
        }
        .stats {
            color: darkorange;
        }
    </style>
    <script src="https://js.arcgis.com/3.34/"></script>
    <script>
        require([
            "esri/map",
            "esri/layers/FeatureLayer",
            "esri/tasks/query",
            "esri/tasks/StatisticDefinition",
            "esri/geometry/geometryEngine",
            "esri/symbols/SimpleMarkerSymbol",
            "esri/symbols/SimpleLineSymbol",
            "esri/symbols/SimpleFillSymbol",
            "esri/graphic",
            "esri/Color",
            "dojo/dom",
            "dojo/domReady!"
        ], function(Map, FeatureLayer, Query, StatisticDefinition, geometryEngine,
                    SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol, Graphic, Color, dom) {

            var map = new Map("map", {
                basemap: "streets-night-vector",
                center: [-122.304568, 47.608492],
                zoom: 13
            });
            //要素服务的url
            var url = "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Puget_Sound_BG_Food/FeatureServer/0";

            /******************************************************************
             *
             * The fields used to query for statistics
             * ALAND is land area in square meters 面积
             * TOTPOP_CY is total population in the block group (2015) 人口数量
             * HasData indicates if data is available in the feature
             *
             *******************************************************************/

            var fields = [ "ALAND", "TOTPOP_CY", "HasData", "TOTHH" ];

            // 要素图层
            var blockGroupsLyr = new FeatureLayer(url, {
                outFields: fields
            });
            console.log(blockGroupsLyr);
            // 用于表示地图上单击的符号
            var pointSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 10, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([0,255,0, 0.3]), 10), new Color([0,255,0,1]));

            // 用于表示点击周围一英里缓冲区符号
            var buffSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_LONGDASHDOT, new Color([255,128,0,1]), 3), new Color([255,128,0,0.15]));

            var fill = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID, new SimpleLineSymbol(SimpleLineSymbol.STYLE_LONGDASHDOT, new Color([255,0,0,1]), 3), new Color([0,255,0,0.6]));

            // When the map is clicked, get the point at the clicked location and execute getPoint()
            // 单击地图时,在单击的位置获取点并执行getPoint()
            map.on("click", getPoint);

            /******************************************************************
             *
             * The sqlExpression is a standard SQL expression that will be used to
             * query the service for statistics. Since the ALAND field represents the
             * land area in square meters, we want to convert the units to square
             * miles. Therefore `(ALAND * 0.0000003861)` will return the area in square
             * miles. Dividing the TOTPOP_CY by that expression will return the
             * population per square mile.
             *
             * This expression is then set on the onStatisticField property of each
             * statistic definition object. Since we don't have a field for population
             * density in people per square mile, we can use this simple SQL expression
             * in the place of a field and we'll get our desired result:
             *
             * "TOTPOP_CY / (ALAND * 0.0000003861)"
             *
             *******************************************************************/
                //SQL表达式只支持要素服务人口除以面积得到人口密度(我改成算一公里内的人口密度)
            var sqlExpression = "TOTPOP_CY / (ALAND * 0.000001)";

            // Object used to request the smallest population density from the
            // block groups within one mile of the mouse click.
            var minStatDef = new StatisticDefinition();
            // 统计类型
            minStatDef.statisticType = "min";
            //将对其计算统计信息的字段名或标准SQL表达式
            minStatDef.onStatisticField = sqlExpression;
            //指定输出字段名
            minStatDef.outStatisticFieldName = "minPopDensity";

            // Object used to request the largest population density from the
            // block groups within one mile of the mouse click.
            var maxStatDef = new StatisticDefinition();
            maxStatDef.statisticType = "max";
            maxStatDef.onStatisticField = sqlExpression;
            maxStatDef.outStatisticFieldName = "maxPopDensity";

            // Object used to request the average population density for
            // all block groups within one mile of the mouse click.
            var avgStatDef = new StatisticDefinition();
            avgStatDef.statisticType = "avg";
            avgStatDef.onStatisticField = sqlExpression;
            avgStatDef.outStatisticFieldName = "avgPopDensity";

            // Object used to request the number of
            // block groups within one mile of the mouse click.
            var countStatDef = new StatisticDefinition();
            countStatDef.statisticType = "count";
            countStatDef.onStatisticField = sqlExpression;
            countStatDef.outStatisticFieldName = "numBlockGroups";

            // Object used to request the standard deviation of the population density for
            // all block groups within one mile of the mouse click.
            var stddevStatDef = new StatisticDefinition();
            stddevStatDef.statisticType = "stddev";
            stddevStatDef.onStatisticField = sqlExpression;
            stddevStatDef.outStatisticFieldName = "StdDevPopDensity";

            // Set the base parameters for the query. All statistic definition objects
            // are passed as an array into the outStatistics param
            //查询参数
            var queryParams = new Query();
            //控制
            queryParams.distance = 2;  // Return all block groups within one mile of the point
            queryParams.units = "kilometers";
            queryParams.outFields = fields;
            //统计字段
            queryParams.outStatistics = [minStatDef, maxStatDef, avgStatDef, countStatDef, stddevStatDef];

            // Executes on each map click
            function getPoint(evt){

                // Set the location of the mouse click event to the query parameters
                //点击的点
                var point = evt.mapPoint;
                //空间过滤条件(空间关系),如果只设置了geometry,未设置spatialRelationship,spatialRelationship有一个默认值是Query.SPATIAL_REL_INTERSECTS
                queryParams.geometry = point;
                // queryParams.spatialRelationship = Query.SPATIAL_REL_INTERSECTS;

                // Clear the graphics from any previous queries
                map.graphics.clear();

                // Add a point graphic represting the location clicked on the map
                var ptGraphic = new Graphic(point, pointSymbol);
                map.graphics.add(ptGraphic);//画了一个点击点

                // Add a graphic representing a one-mile buffer around the clicked point
                var buffer = geometryEngine.geodesicBuffer(point, 1, "kilometers");//投影是wgs1984或者web墨卡托就使用这个,否则就是用buffer()
                var bufferGraphic = new Graphic(buffer, buffSymbol);
                map.graphics.add(bufferGraphic);//在点击点的位置画了一个buffer

                // Execute the statistics query against the feature service and call the getStats() callback
                blockGroupsLyr.queryFeatures(queryParams, getStats, errback);
            }

            // Executes on each query
            function getStats(results){
                console.log(results);
                var graphics = results.features;
                for (var i = 0; i < graphics.length; i++) {
                    console.log(graphics[i]);
                    var graphic = graphics[i];
                    graphic.setSymbol(fill);
                    map.graphics.add(graphic);
                }

                // The return object of the query containing the statistics requested
                var stats = results.features[0].attributes;

                // Print the statistic results to the DOM
                dom.byId("countResult").innerHTML = Math.round(stats.numBlockGroups);
                dom.byId("minResult").innerHTML = Math.round(stats.minPopDensity) + " people/sq mi";
                dom.byId("maxResult").innerHTML = Math.round(stats.maxPopDensity) + " people/sq mi";
                dom.byId("avgResult").innerHTML = Math.round(stats.avgPopDensity) + " people/sq mi";
                dom.byId("stdDevResult").innerHTML = Math.round(stats.StdDevPopDensity) + " people/sq mi";
            }

            function errback(err){
                console.log("Couldn't retrieve summary statistics. ", err);
            }
        });
    </script>
</head>

<body>
<div id="map"></div>
<div id="results"><h3>Summary Statistics</h3>
    Click on the map to view summary statistics of the
    population density for U.S. Census block groups within
    one mile of the clicked point.<br><br>
    <div id="display">
        <strong>Block groups: </strong><span class="stats" id="countResult"></span><br>
        <strong>Min density: </strong><span class="stats" id="minResult"></span><br>
        <strong>Max density: </strong><span class="stats" id="maxResult"></span><br>
        <strong>Average density: </strong><span class="stats" id="avgResult"></span><br>
        <strong>Standard deviation: </strong><span class="stats" id="stdDevResult"></span>
    </div>
</div>
</body>
</html>


总结

本文通过该实例得出了Query中的几个参数的具体含义,包括:distance+until+geometry来设置了查询的缓冲区的空间过滤、还包括geometry参数与空间关系spatialRelationship搭配使用的,如果单独只给geometry的话就会只用spatialRelationship的默认值Query.SPATIAL_REL_INTERSECTS。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值