基於REST的方式訪問Portal的GA工具

Portal、GA和REST API簡介

Portal for ArcGIS是一個門戶網站,可用戶與組織內的其他人便捷地分享地圖、場景、應用和其他地理信息。

GeoAnalytics Server是ArcGIS產品體系中針對空間大數據做高級分析的軟件產品,可通過ArcGIS Pro或者Portal for ArcGIS執行大數據分析,也可以通過REST的方式進行遠程調用。

ArcGIS REST API方便開發者將ArcGIS服務和功能集成到應用程序中,可實現訪問ArcGIS服務(如地理編碼和路由),也可以構建與ArcGIS Online和ArcGIS Enterprise深度集成的應用程序。

本篇博客一個GA的Overlay工具爲例,介紹如何通過REST API訪問Portal中的GA工具。通過訪問REST API中的Overlay工具描述,可以瞭解到輸入參數和響應結果信息。

疊加圖層的選擇

在實際應用中,常常使用發佈的大數據的服務地址作爲疊加工具的輸入圖層。疊加工具的疊加要素的選擇基本上是有兩種選擇:一種是服務地址,一種是Feature Collection。經過對比測試,前者要比後者更穩定一些。因此,本篇博客使用服務地址作爲疊加工具的疊加圖層參數。

考慮到用戶的實際需求(比如:上傳一個SHP文件或者手繪一個範圍並以此作爲疊加要素,即:疊加要素是經常變的),因此建議發佈一個要素服務,設置其爲可編輯狀態(如下圖所示),然後將其作爲疊加工具的疊加要素。
設置要素服務可編輯狀態
在前端頁面實現上訴思路時,在繪製疊加範圍或者上傳SHP文件之前需要將這個要素服務清空,然後將繪製的範圍或SHP文件內容添加到這個要素服務中。

下面的代碼先對要素圖層進行要素檢索,如果有要素,則將其刪除,然後將新的要素添加到該服務中;如果沒有要素,則直接將新的要素添加該服務中。

overlayLayer.queryFeatures().then(function(results) {
    if (results.features.length > 0) {
        overlayLayer
          .applyEdits({
            deleteFeatures: results.features
          })
          .then(function(_) {
            overlayLayer
              .applyEdits({
                addFeatures: overlayLayerAddingGraphics
              })
              .then(function(editsResult) {
                overlayLayer.refresh();
                
                // do overlay
              })
              .catch(function(error) {
                console.log(error);
              });
          });
    } else {
        overlayLayer
          .applyEdits({
            addFeatures: overlayLayerAddingGraphics
          })
          .then(function(editsResult) {
            overlayLayer.refresh();
            
            // do overlay
          })
          .catch(function(error) {
            console.log(error);
          });
    }
});

疊加範圍的選擇

GA的分析工具的環境設置中默認將輸入圖層的圖層範圍作爲工具的分析範圍。因此,如果你的輸入圖層範圍過大時,建議將工具的分析範圍設置爲疊加圖層的範圍,這樣可以加快工具的執行時間。

疊加結果的存儲方式

GA的分析工具的分析結果存儲方式有兩種,一種是存儲在時空大數據庫中,一種是存儲到關係型數據中,默認是存儲在時空大數據庫中。經過測試,如果選擇存儲到時空大數據庫中,無論是否設置輸出結果的座標系,輸出結果都是WGS84座標系;而存儲到關係數據庫中,如果未指定輸出結果的座標系,輸出結果的座標系和輸入要素的座標系相同,反之爲指定的座標系。因此,這裏建議將處理結果輸出到關係型數據庫中。

整個Overlay分析工具的參數如下如下:

let restData = {
    overlayLayer:
      '{"url": "' + Vue.prototype["featureServerUrl"] + '"}',
    inputLayer:
      '{"url": "' +
      Vue.prototype["overlayFeatureServerUrl"] +
      '"}',
    overlayType: "Intersect",
    includeOverlaps: "false",
    outputName: that.gaOutputName,
    context: "",
    f: "json",
    token: portalToken
};

let context = {
    extent: getOverlayLayerExtent(
      that.esriView,
      quickClipSettingParams.selectedClipInputLayer
    ),
    processSR: overlayLayer.spatialReference,
    dataStore: "relational"
};

restData.context = JSON.stringify(context);

執行疊加工具

疊加工具的參數配置完成後,可以使用ajax或axios方式發送POST請求,請求執行疊加分析,實現代碼如下:

export const postRequestOfAxios = (
  requestUrl,
  requestData,
  successfulCallback,
  failCallback
) => {
  axios
    .post(requestUrl, requestData, {
      timeout: 3600000,
      cache: false,
      async: false,
      dataType: "jsonp"
    })
    .then(function(requestResultInfo) {
      successfulCallback(requestResultInfo);
    })
    .catch(function(requestErrorInfo) {
      failCallback(requestErrorInfo);
    });
}
postRequestOfAxios(
    postRequestUrl,
    qs.stringify(restData),
    function(requestResultInfo) {
        let jobId = requestResultInfo.data.jobId;
        
        // Check Job Status
    },
    function(requestErrorInfo) {
      console.log(requestErrorInfo);
    }
);

檢查疊加分析任務的狀態,獲取疊加分析結果圖層地址

正如上述代碼所示,疊加分析的POST請求會返回一個對應的JOB ID,並不會直接返回疊加結果的圖層地址。這是因爲疊加分析需要一定的時間,因此我們需要使用這個JOB ID訪問疊加分析任務的狀態,直到分析成功或者分析失敗。

這裏使用setInterval方法,每個2s查詢一次疊加分析任務的狀態。

that.overlayWindowsInterval = window.setInterval(
    function() {
        checkGAToolStatus(
            overlayToolsUrl,
            jobId,
            Vue.prototype["portalDomainName"],
            portalToken,
            that.overlayWindowsInterval,
            that.esriView,
            successCallBack,
            failCallBack
        );
    },
    2000
);
function checkGAToolStatus(
  gaToolUrl,
  gaToolJobId,
  portalDomainName,
  portalToken,
  overlayWindowsInterval,
  esriView,
  successCallBack,
  failCallBack
) {
  let jobUrl = gaToolUrl + "/jobs/" + gaToolJobId;
  let data = {
    f: "pjson",
    token: portalToken
  };

  postRequestOfAxios(
    jobUrl,
    qs.stringify(data),
    function(requestResultInfo) {
      let jobStatus = requestResultInfo.data.jobStatus;

      if (
        jobStatus === "esriJobSubmitted" ||
        jobStatus === "esriJobWaiting" ||
        jobStatus === "esriJobExecuting"
      ) {
        console.log(jobStatus);
      } else if (
        jobStatus === "esriJobFailed" ||
        jobStatus === "esriJobTimedOut" ||
        jobStatus === "esriJobCancelling" ||
        jobStatus === "esriJobCancelled"
      ) {
        window.clearInterval(overlayWindowsInterval);

        failCallBack();

        console.log(jobStatus);
      } else if (jobStatus === "esriJobSucceeded") {
        window.clearInterval(overlayWindowsInterval);

        let jobOutputRequestUrl = jobUrl + "/results/output";

        postRequestOfAxios(
          jobOutputRequestUrl,
          qs.stringify(data),
          function(requestResultInfo) {
            esriLoader
              .loadModules(["esri/layers/FeatureLayer"], gisConfig.arcgisApi)
              .then(([EsriFeatureLayer]) => {
                let gaResultFeatureLayer = findLayerById(
                  esriView,
                  gisConfig.overlayResultLayerId
                );

                if (gaResultFeatureLayer) {
                  esriView.map.remove(gaResultFeatureLayer);
                }

                gaResultFeatureLayer = new EsriFeatureLayer({
                  url: requestResultInfo.data.value.url,
                  id: gisConfig.overlayResultLayerId,
                  title: "裁剪結果"
                });

                esriView.map.add(gaResultFeatureLayer);

                successCallBack();
              });
          },
          function(requestErrorInfo) {
            console.log(requestErrorInfo);

            failCallBack();
          }
        );
      }
    },
    function(requestErrorInfo) {
      console.log(requestErrorInfo);

      failCallBack();
    }
  );
}

至此,我們已經完成了通過REST調用GA的Overlay工具並將結果顯示在當前地圖中的整個流程。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章