Escrevi várias automações do ArcGIS VBA na pós-graduação; no entanto, eles são totalmente dependentes da extensão do ArcGIS Spatial Analyst, que não é apenas de código fechado, mas caro, a ponto de impedir.
Como o VBA está obsoleto e como alguns pesquisadores da U ainda usam minhas ferramentas de VBA, pensei que seria divertido reescrevê-las no .Net. Mas agora, com mais experiência, percebo ainda que seria mais apropriado para uso acadêmico se esses utilitários consumissem algoritmos abertos.
Com isso em mente, estou considerando o Whitebox GAT como um substituto em potencial para as ferramentas de hidrologia do Spatial Analyst, e estou curioso para saber se há histórias de sucesso ou dicas de economia de tempo relacionadas à integração do ArcGIS / Whitebox.
Eu espero que várias pessoas queiram sugerir a implementação de Saga, GRASS, R, etc. Se essa é a sua posição, descreva por que não é aconselhável seguir uma integração do Whitebox. Por exemplo, ele suporta apenas alguns formatos de entrada, possui um tratamento inadequado de arquivos grandes (1-2 GB +) etc.
Eu brinquei com a interface do usuário do Whitebox e, com a ajuda de seus tutoriais , não foi difícil pré-processar um DEM de 30 metros que eu tinha por perto. Em seguida, depois de alinhar os raspadores hidráulicos, criei um ponto de fluidez e renderizei sua bacia hidrográfica. Isso foi suficiente para ter uma ideia da experiência do usuário do Whitebox.
O Whitebox é extensível e / ou consumível usando .Net ou Python. Tendo realizado alguns conceitos básicos na interface do usuário do Whitebox, pensei em encadear as tarefas típicas de pré-processamento do DEM com uma simples automação .Net (ainda não havia ArcMap). O pré-processamento do DEM geralmente significa o seguinte:
- não defina nenhum valor de dados (o Whitebox precisa disso, mas o Arc nunca)
- encher pias
- criar uma varredura de direção de fluxo
- criar uma varredura de acumulação de fluxo
Eu montei o seguinte formulário do Windows "aplicativo" (aka WhiteboxDaisyChain
). Ele pega um diretório do sistema que contém uma ArcGIS Grid (.FLT) e executa as tarefas mencionadas acima. Se você quiser tentar isso, precisará fazer o download dos binários compilados , descompactar e copiar todos os .dll
arquivos do ..\WhiteboxGAT_1_0_7\Plugins
seu projeto - coloquei tudo ..\WhiteboxDaisyChain\Whitebox
. No entanto, este exemplo precisa apenas dos quatro DLLs
mencionados na parte superior do exemplo de código.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
// 1) Create a new Windows Form
// 2) Put all these in a Whitebox folder in the C# project root.
// 3) Add project references to the following and create using statements:
using Interfaces; // requires Add Reference: Interfaces.dll
using ImportExport; // requires Add Reference: ImportExport.dll
using ConversionTools; // requires Add Reference: ConversionTools.dll
using flow; // requires Add Reference: flow.dll
namespace WhiteboxDaisyChain
{
// 4) Prepare to implement the IHost interface.
// 5) Right-click IHost, select "Implement interface.."
public partial class UI : Form, IHost
{
// 6) Add a BackgroundWorker object.
private BackgroundWorker worker;
public UI()
{
InitializeComponent();
// 7) Instantiate the worker and set "WorkerReportsProgress".
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
}
// 8) Use some event to set things in motion.. i.e. Button click.
private void button1_Click(object sender, EventArgs e)
{
progressLabel.Text = "Running..";
// This is the path containing my ArcGrid .FLT.
// All processing will unfold to this directory.
string path = "C:\\xData\\TutorialData\\DemWhitebox\\";
string[] fltArgs = new string[1];
fltArgs[0] = path + "greene30.flt"; // in: Arc floating point grid
// creates a raster in Whitebox data model
ImportArcGrid importAG = new ImportArcGrid();
importAG.Initialize(this as IHost);
importAG.Execute(fltArgs, worker); // out: path + "greene30.dep"
// set the nodata value on the DEM
string[] noDataArgs = new string[2];
noDataArgs[0] = path + "greene30.dep"; // in: my raw DEM
noDataArgs[1] = "-9999"; // mine used -9999 as nodata value
SetNoData setNoData = new SetNoData();
setNoData.Initialize(this as IHost);
setNoData.Execute(noDataArgs, worker); // out: path + "greene30.dep"
// fill sinks in the DEM
string[] fillSinksArgs = new string[4];
fillSinksArgs[0] = path + "greene30.dep"; // in: my DEM with NoData Fixed
fillSinksArgs[1] = path + "greene30_fill.dep"; // out: my DEM filled
fillSinksArgs[2] = "50"; // the dialog default
fillSinksArgs[3] = "0.01"; // the dialog default
FillDepsBySize fillSinks = new FillDepsBySize();
fillSinks.Initialize(this as IHost);
fillSinks.Execute(fillSinksArgs, worker);
// create a flow direction raster
string[] flowDirArgs = new string[2];
flowDirArgs[0] = path + "greene30_fill.dep"; // in: my Filled DEM
flowDirArgs[1] = path + "greene30_dir.dep"; // out: flow direction raster
FlowPointerD8 flowDirD8 = new FlowPointerD8();
flowDirD8.Initialize(this as IHost);
flowDirD8.Execute(flowDirArgs, worker);
// create a flow accumulation raster
string[] flowAccArgs = new string[4];
flowAccArgs[0] = path + "greene30_dir.dep"; // in: my Flow Direction raster
flowAccArgs[1] = path + "greene30_acc.dep"; // out: flow accumulation raster
flowAccArgs[2] = "Specific catchment area (SCA)"; // a Whitebox dialog input
flowAccArgs[3] = "false"; // a Whitebox dialog input
FlowAccumD8 flowAccD8 = new FlowAccumD8();
flowAccD8.Initialize(this as IHost);
flowAccD8.Execute(flowAccArgs, worker);
progressLabel.Text = "";
progressLabel.Text = "OLLEY-OLLEY-OXEN-FREE!";
}
/* IHost Implementation Methods Below Here */
public string ApplicationDirectory
{
get { throw new NotImplementedException(); }
}
public void ProgressBarLabel(string label)
{
this.progressLabel.Text = "";
this.progressLabel.Text = label; // This is the only one I used.
}
public string RecentDirectory
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public bool RunInSynchronousMode
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public void RunPlugin(string PluginClassName)
{
throw new NotImplementedException();
}
public void SetParameters(string[] ParameterArray)
{
throw new NotImplementedException();
}
public void ShowFeedback(string strFeedback, string Caption = "GAT Message")
{
throw new NotImplementedException();
}
}
}
Até agora, estou pesquisando isso, mas ainda não tenho uma história de sucesso real ou nenhum tipo de restrição para descrever .. Meu próximo objetivo será enviar interativamente pontos de fluidez do ArcMap. Basicamente, quero clicar no mapa ..obter a bacia hidrográfica.