1. 程式人生 > >ArcGIS API For JS之網路分析(臨近設施分析)

ArcGIS API For JS之網路分析(臨近設施分析)

ArcGIS 提供兩種網路分析,即基於Geometric Network的有向網路或者設施網路和基於Network Dataset的無向網路,在這裡網路的分析指後者,ArcGIS api支援網路分析中的最短路徑分析、服務區分析、臨近設施分析。本文主要講的是臨近設施分析,關於釋出網路服務在這裡就不在敘述了,三種分析釋出相同,只是在後臺ArcMap中處理方式有點區別。

一、概述

1、概念

臨近設施服務計算事件和設施之間的行駛成本,並決定那一個距離最近,最後給出最佳的路徑,在這裡認為,這算是最短距離的升級版本

2、相關的類

  • ClosestFacilityTask(執行命令,宣告需要一個Rest資源,即NAServer服務)
  • ClosestFacilityParameters(引數)
  • ClosestFacilitySolveResult(處理結果)(這裡沒用到,該類用處非常大)

二、引數宣告與設定

            closestFacilityTask = new ClosestFacilityTask("http://localhost:6080/arcgis/rest/services/Test/CloseFacilityTest/NAServer/CloseFacility");
            //臨近設施分析引數
            var params = new ClosestFacilityParameters();
            //單位
            params.impedenceAttribute = "Miles";
            params.defaultCutoff = 7.0;
            //是否返回事件資訊
            params.returnIncidents = false;
            //是否返回路徑
            params.returnRoutes = true;
            //路徑是否有引數
            params.returnDirections = true;
            //服務點
            params.facilities = new FeatureSet();
            //事件點
            params.incidents = new FeatureSet();
            //點障礙
            params.pointBarriers = new FeatureSet();
            //空間參考
            params.outSpatialReference = map.SpatialReference;

在這裡有很多引數可以設定,服務點、事件點、路徑、空間參考,是必須要設定的,其他引數可以根據自己需要設定,這裡FeatureSet是要素類的輕量級的表示,相當於地理資料中的一個要素類,Feature的集合,FeatureSet中的每個Feature可能包含Geometry、屬性、符號、InfoTemplate。FeatureSet是api和arcgis server通訊的非常重要的物件。當使用查詢、地理出咯i和路徑分析的時候,FeatureSet常常作為這些分析功能的輸入或輸出引數。

三、符號樣式

            //服務點符號樣式
            var facilityPointSymbol = new SimpleMarkerSymbol(
              SimpleMarkerSymbol.STYLE_SQUARE,
              20,
              new SimpleLineSymbol(
                SimpleLineSymbol.STYLE_SOLID,
                new Color([89, 95, 35]), 2
              ),
              new Color([130, 159, 83, 0.40])
            );
            //事件點符號樣式
            var incidentPointSymbol = new SimpleMarkerSymbol(
              SimpleMarkerSymbol.STYLE_CIRCLE,
              16,
              new SimpleLineSymbol(
                SimpleLineSymbol.STYLE_SOLID,
                new Color([89, 95, 35]), 2
              ),
              new Color([130, 159, 83, 0.40])
            );
            //障礙點的符號樣式
            var barrierSymbol = new SimpleMarkerSymbol();
            barrierSymbol.style = SimpleMarkerSymbol.STYLE_X;
            barrierSymbol.setSize(12);
            barrierSymbol.setColor(new Color("#f1a340"));
            incidentsGraphicsLayer = new GraphicsLayer();
            //結果路徑線符號樣式
            var routePolylineSymbol = new SimpleLineSymbol(
              SimpleLineSymbol.STYLE_SOLID,
              new Color("#0078df"),
              4.0
            );

四、分析結果處理

function showRoute(solveResult) {
                //路徑分析的結果
                var routeResults = solveResult.routes;
                //路徑分析的長度
                var res = routeResults.length;
                if (res > 0) {

                    for (var i = 0; i < res; i++) {
                        var graphicroute = routeResults[i];
                        var graphic = graphicroute;
                        graphic.setSymbol(routePolylineSymbol);
                        map.graphics.add(graphic);
                    }
                }
                else {
                    alert("沒有返回結果");
                }
            }

五、全部原始碼

<!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>Closest Facilities</title>

    <link rel="stylesheet" href="https://js.arcgis.com/3.25/dijit/themes/claro/claro.css">
    <link rel="stylesheet" href="https://js.arcgis.com/3.25/esri/css/esri.css">
    <style type="text/css">
        #map
        {
            width: 100%;
            height: 600px;
            border: 1px solid #000;
        }
    </style>
    <script src="https://js.arcgis.com/3.25/"></script>
    <script src="../Scripts/jquery-1.7.1.js"></script>
    
</head>

<body>
    <div id="map"></div>
    <input id="server" type="button" value="服務點" />
    <input id="eventPoint" type="button" value="事件點" />
    <input id="barriers" type="button" value="障礙點" />
    <input id="analyse" type="button" value="分析" />
    <input id="clear" type="button" value="清除" />
    <script>       
        require([
            "dojo/on",
          "dojo/dom",
          "dojo/_base/array",
          "esri/Color",
          "dojo/parser",
          "dijit/registry",

          "esri/urlUtils",
          "esri/map",
          "esri/lang",
          "esri/graphic",
          "esri/InfoTemplate",
          "esri/layers/GraphicsLayer",
          "esri/renderers/SimpleRenderer",
          "esri/layers/ArcGISDynamicMapServiceLayer",

          "esri/geometry/Point",
          "esri/tasks/FeatureSet",

          "esri/tasks/ClosestFacilityTask",
          "esri/tasks/ClosestFacilityParameters",

          "esri/symbols/SimpleMarkerSymbol",
          "esri/symbols/SimpleLineSymbol",
          "esri/symbols/TextSymbol",

          "dijit/form/ComboBox",
          "dijit/layout/BorderContainer",
          "dijit/layout/ContentPane"
        ], function (
          on, dom, array, Color, parser, registry,
          urlUtils, Map, esriLang, Graphic, InfoTemplate, GraphicsLayer, SimpleRenderer, ArcGISDynamicMapServiceLayer,
          Point, FeatureSet,
          ClosestFacilityTask, ClosestFacilityParameters,
          SimpleMarkerSymbol, SimpleLineSymbol, TextSymbol
        ) {
            var incidentsGraphicsLayer, routeGraphicLayer, closestFacilityTask;

            var map = new Map("map");
            var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://localhost:6080/arcgis/rest/services/Test/CloseFacilityTest/MapServer");
            map.addLayer(layer)
            closestFacilityTask = new ClosestFacilityTask("http://localhost:6080/arcgis/rest/services/Test/CloseFacilityTest/NAServer/CloseFacility");
            //臨近設施分析引數
            var params = new ClosestFacilityParameters();
            //單位
            params.impedenceAttribute = "Miles";
            params.defaultCutoff = 7.0;
            //是否返回事件資訊
            params.returnIncidents = false;
            //是否返回路徑
            params.returnRoutes = true;
            //路徑是否有引數
            params.returnDirections = true;
            //服務點
            params.facilities = new FeatureSet();
            //事件點
            params.incidents = new FeatureSet();
            //點障礙
            params.pointBarriers = new FeatureSet();
            //空間參考
            params.outSpatialReference = map.SpatialReference;
            //服務點符號樣式
            var facilityPointSymbol = new SimpleMarkerSymbol(
              SimpleMarkerSymbol.STYLE_SQUARE,
              20,
              new SimpleLineSymbol(
                SimpleLineSymbol.STYLE_SOLID,
                new Color([89, 95, 35]), 2
              ),
              new Color([130, 159, 83, 0.40])
            );
            //事件點符號樣式
            var incidentPointSymbol = new SimpleMarkerSymbol(
              SimpleMarkerSymbol.STYLE_CIRCLE,
              16,
              new SimpleLineSymbol(
                SimpleLineSymbol.STYLE_SOLID,
                new Color([89, 95, 35]), 2
              ),
              new Color([130, 159, 83, 0.40])
            );
            //障礙點的符號樣式
            var barrierSymbol = new SimpleMarkerSymbol();
            barrierSymbol.style = SimpleMarkerSymbol.STYLE_X;
            barrierSymbol.setSize(12);
            barrierSymbol.setColor(new Color("#f1a340"));
            incidentsGraphicsLayer = new GraphicsLayer();
            //結果路徑線符號樣式
            var routePolylineSymbol = new SimpleLineSymbol(
              SimpleLineSymbol.STYLE_SOLID,
              new Color("#0078df"),
              4.0
            );
            //定義一個標誌
            //selectPointID=0什麼都不做
            //selectPointID=1是新增服務點
            //selectPointID=2是新增事件點
            //selectPointID=3是新增障礙點
            var selectPointID;
            //新增服務點
            $("#server").click(function () {
                selectPointID = 1;
            });
            //新增事件點
            $("#eventPoint").click(function () {
                selectPointID = 2;
            });
            //新增障礙點
            $("#barriers").click(function () {
                selectPointID = 3;
            });
            //清除所有障礙、事件、服務點和路徑線
            on(map, "mouse-down", function (evt) {
                //通過selectPointID判斷是新增是停靠點還是障礙點
                switch (selectPointID) {
                    case 0:
                        break;
                    case 1:
                        //獲得服務點的座標
                        var pointServer = evt.mapPoint;
                        var gr = new Graphic(pointServer, facilityPointSymbol);
                        //構建服務點的引數
                        params.facilities.features.push(gr);
                        break;
                    case 2:
                        //獲得事件點的座標
                        var pointEvent = evt.mapPoint;
                        var gr = new Graphic(pointEvent, incidentPointSymbol);
                        //構建事件點的引數
                        params.incidents.features.push(gr);
                        break;
                    case 3:
                        //獲得障礙點的座標
                        var pointBarrier = evt.mapPoint;
                        var gr = new Graphic(pointBarrier, barrierSymbol);
                        //構建障礙點的引數
                        params.pointBarriers.features.push(gr);
                        break;
                }
                //如果selectPointID不等於0,將點的座標在地圖上顯示出來
                if (selectPointID != 0) {
                    addTextPoint("服務點", pointServer, facilityPointSymbol);
                    addTextPoint("事件點", pointEvent, incidentPointSymbol);
                    addTextPoint("障礙點", pointBarrier, barrierSymbol);
                    
                }
            });
            //文字符號:文字資訊,點座標,符號
            function addTextPoint(text, point, symbol) {
                var textSymbol = new TextSymbol(text);
                textSymbol.setColor(new Color([128, 0, 0]));
                var graphicText = Graphic(point, textSymbol);
                var graphicpoint = new Graphic(point, symbol);
                //用預設的圖層新增
                map.graphics.add(graphicpoint);
                map.graphics.add(graphicText);
            }
            //分析執行事件
            $("#analyse").click(function () {
                selectPointID = 0;
                //如果服務點或者事件點的個數有一個為0,提示使用者引數輸入不對
                if (params.facilities.features.length == 0 || params.incidents.features.length == 0) {
                    alert("輸入引數不全,無法分析");
                    return;
                }
                //執行路徑分析函式
                closestFacilityTask.solve(params, showRoute)
            });
            //處理路徑分析返回的結果。
            function showRoute(solveResult) {
                //路徑分析的結果
                var routeResults = solveResult.routes;
                //路徑分析的長度
                var res = routeResults.length;
                if (res > 0) {

                    for (var i = 0; i < res; i++) {
                        var graphicroute = routeResults[i];
                        var graphic = graphicroute;
                        graphic.setSymbol(routePolylineSymbol);
                        map.graphics.add(graphic);
                    }
                }
                else {
                    alert("沒有返回結果");
                }
            }
        });
    </script>
</body>
</html>

六、成果圖


七、總結

在這裡我為了省事引數設定的不多,三種分析其實差別不是很大,使用的方式也比較相似,如果說噁心應該是在釋出資料之前的構造網路,錯誤出一堆,奈何我對著不是個很瞭解,浪費了很多的時間,技術不行還需要很多努力。