天天看點

ArcGIS API for JavaScript 4.2學習筆記[28] 可視域分析【使用Geoprocessor類】

使用Geoprocessor這個類,可以處理很多事情。比如這裡的可視域分析。

想知道可視域分析是什麼,就得知道可視域是什麼

我們站在某個地方,原地不動轉一圈能看到的所有事物就叫可視域。當然平地就沒什麼所謂的可視域。

如果在山區呢?可視範圍就會被山體擋住了。這個分析對軍事上有十分重要的意義。

在本例中,可視域是以GraphicLayer中的Graphics[]形式存在的。

這個例子用到了Geoprocessor這個類。這個類的對象是如何判别我要進行可視域分析呢?且聽我慢慢道來。

看看結果

ArcGIS API for JavaScript 4.2學習筆記[28] 可視域分析【使用Geoprocessor類】

點選山谷的位置,出現一個紅點,稍等10s左右,出現橙色的面塊,橙色的面塊就是紅點位置所能看到的範圍了(比起桌面的可視域分析還是弱了點),比起桌面來說可謂是所見即所得。

這個在AJS 3.x是做不到的,因為這裡有強大的3D分析功能嘛。

Geoprocessor類

這個類很強大,和之前的四個Task不太一樣,它接受的處理參數不再是一個類,而是一個Object數組。也就是說,是什麼樣子的處理,就輸入什麼樣的參數。

官方舉例如下:

假設有Input_Points和Distance兩個需要輸入的參數,那麼

ArcGIS API for JavaScript 4.2學習筆記[28] 可視域分析【使用Geoprocessor類】

就在Geoprocessor類的execute()方法中傳入這麼一個Object對象:

{
   Input_Points: <FeatureSet>,
   Distance: <Number>
}      

這就是GP類的強大之處。如果需要進行異步操作,則使用submitJob()代替execute()方法,節約網頁等待時間。

Geoprocessor類的execute()方法傳回一個Object對象,其包含有:

ArcGIS API for JavaScript 4.2學習筆記[28] 可視域分析【使用Geoprocessor類】

兩個屬性,我們關心的是results屬性,其為ParameterValue[]類型。下面我就要說說ParameterValue這個類,它和前面某某Result類十分相似。

ParameterValue類

ArcGIS API for JavaScript 4.2學習筆記[28] 可視域分析【使用Geoprocessor類】

它是execute()或submitJob()的傳回值中的results屬性類型。

它有三個屬性:dataType(String類型)、declareClass和value(Object類型)

什麼意思呢?GP處理的結果當然是因輸入的參數決定的,是以在本例中,dataType就規定成了"record-set"或"feature-record-set-layer", 即value屬性就被裝箱成了FeatureSet類型。

dataType的值就确定了value的值類型,見這個表格:點我

有了這些預備知識,講解這個例子和下一個例子就不難了。

 給出引用

require([
    "esri/Map",
    "esri/views/SceneView",
    "esri/layers/GraphicsLayer","esri/Graphic",
    "esri/geometry/Point",
    "esri/symbols/SimpleMarkerSymbol","esri/symbols/SimpleFillSymbol",
    "esri/tasks/Geoprocessor",
    "esri/tasks/support/LinearUnit","esri/tasks/support/FeatureSet",
    "dojo/domReady!"
  ],
  function(Map, SceneView, GraphicsLayer, Graphic, Point,
    SimpleMarkerSymbol, SimpleFillSymbol, Geoprocessor,
    LinearUnit, FeatureSet) {
    ...
    }
);      

嗯,對Geoprocessor的引用。

函數架構

function(...){
    var gpUrl ="https://sampleserver6.arcgisonline.com/arcgis/rest/services/Elevation/ESRI_Elevation_World/GPServer/Viewshed";
    var map = new Map({...});
    var view = new SceneView({...});
    var graphicsLayer = new GraphicsLayer({...)};
    map.add(graphicsLayer);
    
    var markerSymbol = new SimpleMarkerSymbol({...});
    var fillSymbol = new SimpleFillSymbol({...});
    
    var gp = new Geoprocessor(gpUrl);
    gp.outSpatialReference = {...};

    //重點
    view.on("click", computeViewshed);
    
    function computeViewshed(event){...}
    function drawResultData(result){...}
}      

我想到這,就不必解釋很多了,我們直接關注資料處理的重點代碼:view的click事件和兩個處理函數computeViewshed()和drawResultData()。

gp這個Geoprocessor類的執行個體化在上方已經說明了,就不說那麼詳細了。

computeViewshed(event)方法

這個方法有點長,但是每一行的意義都很明确。它做的就是擷取點選點,生成一個紅色的點符号,然後擷取gp.execute()的輸入參數,執行execute()方法。

ArcGIS API for JavaScript 4.2學習筆記[28] 可視域分析【使用Geoprocessor類】
ArcGIS API for JavaScript 4.2學習筆記[28] 可視域分析【使用Geoprocessor類】
function computeViewshed(event) {
  graphicsLayer.removeAll();

  var point = new Point({
    longitude: event.mapPoint.longitude,
    latitude: event.mapPoint.latitude
  });

  var inputGraphic = new Graphic({
    geometry: point,
    symbol: markerSymbol
  });

  graphicsLayer.add(inputGraphic);

  var inputGraphicContainer = [];
  inputGraphicContainer.push(inputGraphic);
  var featureSet = new FeatureSet();
  featureSet.features = inputGraphicContainer;

  var vsDistance = new LinearUnit();
  vsDistance.distance = 5;
  vsDistance.units = "miles";

  var params = {
    "Input_Observation_Point": featureSet,
    "Viewshed_Distance": vsDistance
  };

  gp.execute(params).then(drawResultData);
}      

computeViewshed()方法

首先,圖形圖層清零,擷取點選點,命名為point(Point類的執行個體);

然後,根據這個point形成一個Graphic對象,名為inputGraphic,添加到圖形圖層中(顯示點選點);

之後,根據可視域分析服務所需的參數

"Input_Observation_Point"和"Viewshed_Distance",分别為FeatureSet類和LinearUnit類的資料

執行個體化所需的參數featureSet對象和vsDistance對象,組成params這個Object對象;

執行gp.execute(params)。

最後,execute(params)接着一個異步操作then(drawResultData),繪制處理結果。

我們已經知道了,這裡傳回的Object對象中results屬性為ParameterValue[]類型。我們隻需從中擷取需要的可視域資料(FeatureSet)即可。

drawResultData()方法

function drawResultData(result) {
  var resultFeatures = result.results[0].value.features;

  var viewshedGraphics = resultFeatures.map(function(feature) {
    feature.symbol = fillSymbol;
    return feature;
  });

  graphicsLayer.addMany(viewshedGraphics);

  view.goTo({
    target: viewshedGraphics,
    tilt: 0
  });
}      

result即為execute()傳回的Object對象,擷取results[0]的value(即FeatureSet)中的features(類型為Graphic[]),命名為resultFeatures。

對這個Graphic[]變量進行周遊(map()方法),對每個Graphic設定填充符号,傳回一個新的Graphic[]變量viewshedGraphics;

然後把這個Graphic[]變量添加到圖形圖層上;

最後讓視圖跳轉到這個圖形圖層。

總結一下

通過單擊,擷取這個點位資訊——通過這個點生成需要的可視域分析所需的參數集(Object類型),傳入gp.execute()——對傳回的Object對象中的可視域進行處理、顯示。

完美!

繼續閱讀