Escribí varias automatizaciones de ArcGIS VBA en la escuela de posgrado; sin embargo, dependen completamente de la extensión ArcGIS Spatial Analyst, que no solo es de código cerrado sino que es costosa hasta el punto de disuasión.
Como VBA está en desuso y dado que algunos investigadores de la U todavía usan mis herramientas VBA, pensé que sería divertido reescribirlas en .Net. Pero ahora, con más experiencia, me doy cuenta de que sería más apropiado para el uso académico si esas utilidades consumieran algoritmos abiertos.
Con esto en mente, estoy considerando Whitebox GAT como un sustituto potencial para las herramientas de hidrología de Spatial Analyst, y tengo curiosidad por saber si hay historias de éxito o "trampas" que ahorren tiempo relacionadas con la integración de ArcGIS / Whitebox.
Anticipo que varias personas querrán contrarrestar la implementación de Saga, GRASS, R, etc. Si esta es su posición, describa por qué sería poco aconsejable la integración de Whitebox. Por ejemplo, solo admite algunos formatos de entrada, tiene un manejo deficiente de archivos grandes (1-2 GB +), etc.
Jugué un poco con la interfaz de usuario de Whitebox, y con la ayuda de sus tutoriales , no fue difícil procesar previamente un DEM de 30 metros que tenía por ahí. Luego, después de alinear los rasters hidro, creé un punto de fluidez y rendericé su cuenca. Esto fue suficiente para tener una idea de la experiencia del usuario de Whitebox.
Whitebox es extensible y / o consumible usando .Net o Python. Habiendo logrado algunos conceptos básicos en la interfaz de usuario de Whitebox, pensé en encadenar las tareas típicas de preprocesamiento de DEM con una simple automatización .Net (todavía no ArcMap). El preprocesamiento DEM generalmente significa lo siguiente:
- no establece ningún valor de datos (Whitebox necesita esto, pero Arc nunca lo hizo)
- llenar sumideros
- crear un ráster de dirección de flujo
- crear un ráster de acumulación de flujo
Reuní la siguiente "aplicación" de Windows Form (aka WhiteboxDaisyChain
). Toma un directorio del sistema que contiene una cuadrícula ArcGIS (.FLT) y realiza las tareas indicadas anteriormente. Si desea probar esto, deberá descargar los archivos binarios compilados , descomprimirlos y luego copiar todos los .dll
archivos de ..\WhiteboxGAT_1_0_7\Plugins
su proyecto. Puse todo en él ..\WhiteboxDaisyChain\Whitebox
. Sin embargo, este ejemplo solo necesita los cuatro DLLs
mencionados en la parte superior del código de muestra.
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();
}
}
}
Hasta ahora estoy cavando esto, pero todavía no tengo una historia de éxito real o algún show-stoppers para describir ... Mi próximo objetivo será enviar puntos de fluidez de forma interactiva desde ArcMap. Básicamente, quiero hacer clic en el mapa ... obtener la cuenca.