Usando las Nuevas Funciones de FeatureSetBy en Arcade para Acceder a otras Capas y Tablas

610
2
12-18-2018 01:59 PM
Labels (1)

Usando las Nuevas Funciones de FeatureSetBy en Arcade para Acceder a otras Capas y Tablas

En el documento Mejoras en Arcade en ArcGIS Online con la Actualización de 5 de diciembre del 2018 ya mencioné las nuevas funciones de Arcade. En este documento indagamos más para explorar las posibilidades que brinden estas funciones.

Objetivo

Considere que contamos con un mapa con 3 capas y una tabla:

  • Hidrantes es una capa de puntos con los hidrantes
  • Sub Sector es una capa de polígonos con los subsectores en el área de interés
  • Sector Hidraulico es una capa uniendo los subsectores a un nivel mayor generando los sectores hidráulicos
  • Hist Mantenimiento es una tabla con la historia de todos los mantenimientos efectuados en cada hidrante

En este ejercicio queremos hacer lo siguiente:

  1. Desde los hidrantes por medio del código del hidrante se quiere mostrar un listado de los mantenimientos almacenados en la historia de mantenimiento.
  2. En los Subsectores la idea es mostrar la cantidad de hidrantes y la media de la edad de los hidrantes en el subsector mediante una operación espacial.
  3. Para cada Sector Hidráulico presentar un listado de los subsectores en el sector hidráulico mediante una operación espacial.

Simbolizar los hidrantes por su edad

Primero que todo, aplicamos una expresión de Arcade para visualizar los hidrantes con base en su edad. Contamos con la fecha de instalación en el campo FECHAINSTALACION y podemos usar la función DateDiff y Now para determinar la edad en años. En la expresión abajo esto se está calculando en las primeras 2 lineas de código. Luego clasificamos el valor en rangos:

var fecha_inst = $feature.FECHAINSTALACION;
var edad = DateDiff(Now(), fecha_inst, "years");
var clase_edad = "";
if (edad > 50) {
    clase_edad = "Mayor a 50 años";
} else if (edad > 40) {
    clase_edad = "Entre 40 y 50 años";
} else if (edad > 30) {
    clase_edad = "Entre 30 y 40 años";
} else if (edad > 20) {
    clase_edad = "Entre 20 y 30 años";
} else if (edad > 10) {
    clase_edad = "Entre 10 y 20 años";
} else if (edad > 5) {
    clase_edad = "Entre 5 y 10 años";
} else {
    clase_edad = "Menor a 5 años";
}

return clase_edad;

El resultado es un texto a lo cual podemos asignar un símbolo representativo (en este caso hacemos uso de los símbolos Firefly):

Mantenemos unos símbolos sencillos para las dos capas de polígonos para evitar distraer la atención de los hidrantes. Además, usamos el mapa base “Lona gris oscuro” para destacar los símbolos de los hidrantes.

Paso 1: Historia de mantenimiento por hidrante

Para el primer paso podemos configurar la siguiente expresión de Arcade:

var tbl = FeatureSetByName($datastore,"Hist_Mantenimiento");
var codigo = $feature["COD_HIDRANTE"];
var sql = "COD_HIDRANTE = '" + codigo + "'";
Console(sql);
var mantenimientos = Filter(tbl, sql);
var cnt = Count(mantenimientos);
var historia = "";
if (cnt > 0) {
    historia = cnt + " Mantenimiento(s):";
    for (var mantenimiento in mantenimientos) {
        var txt_fecha = Text(mantenimiento.Fecha_Mantenimiento, ' - (Y/MM/DD) ');
        var txt_man = txt_fecha + mantenimiento.Mantenimiento;
        historia += TextFormatting.NewLine + txt_man;
    }
} else {
    historia = "No hay mantenimientos";
}

return historia;

Explicación de la expresión:

  • En la primera línea, usando la nueva función FeatureSetByName accedemos a la tabla con la historia por su nombre “Hist_Mantenimiento” en el datastore.
  • En la segunda línea leemos el código del hidrante actual
  • En la tercera línea creamos una consulta SQL
  • En la quinta línea filtramos la tabla de mantenimientos usando la consulta SQL para quedarnos con los registros de mantenimiento del hidrante actual
  • En las siguientes líneas recorremos por los registros de mantenimiento del hidrante y generamos un texto con cada fecha y tipo de mantenimiento
  • Al final devolvemos este listado

El resultado presentamos en una ventana emergente donde hacemos uso de una “visualización de atributos personalizado”:

Al usuario final se ve así:

Paso 2: Resumen de la edad media por subsector

Para el segundo paso queremos desde el subsector encontrar las hidrantes que están ubicados dentro el subsector y determinar su edad media. Este dato nos puede ayudar a enfocar el esfuerzo de nuestras cuadrillas a las zonas que más lo necesiten.

En la ventana emergente de los subsectores configuramos la siguiente expresión de Arcade:

var fs = FeatureSetByName($datastore,"Hidrantes");
var hidrantes = Intersects(fs, $feature);
var cnt = Count(hidrantes);

var edad_tot = 0;
for (var hidrante in hidrantes) {
    var edad = DateDiff(Now(), hidrante.FECHAINSTALACION, "years");
    edad_tot += edad;
}

var resultado = "";
if (cnt > 0) {
    var edad_media = edad_tot / cnt;
    resultado = "Hay " + cnt + " hidrantes en el sub sector";
    resultado += TextFormatting.NewLine + "La edad media de los hidrantes es de " + Round(edad_media, 2) + " años";
} else {
    resultado = "No hay hidrantes en el sub sector";
}

return resultado;

Explicación de la expresión:

  • En la línea 1 se accede a la capa de hidrantes usando la nueva función FeatureSetByName
  • En la segunda línea hacemos un “Intersects” para quedarnos con los hidrantes que están dentro del subsector actual.
  • En la tercera línea determinamos la cantidad de hidrantes en el subsector usando el “Count”
  • Luego recorremos por los hidrantes y calculamos la edad de cada uno y la edad media de todos los hidrantes en el subsector
  • Al final se genere el texto con el resultado y esto se devuelve

El resultado se veré así:

En este ejemplo tenemos 93 hidrantes en el subsector y la edad media es de 20,64 años.

Paso 3: Listado de subsectores por sector hidráulico

Cada sector hidráulico está compuesto por varios subsectores. En este paso queremos presentar un listado de nombres de subsectores por sector hidráulico. Para este fin intentamos con la siguiente expresión de Arcade:

var fs = FeatureSetByName($datastore,"Sub Sector");
var subsectores = Intersects(fs, $feature);
var cnt = Count(subsectores);

var resultado = "Listado de los " + cnt + " Subsectores:";
for (var subsector in subsectores) {
    resultado += TextFormatting.NewLine + subsector.IDSAP;
}

return resultado;

Eso debería devolver el listado de nombres, de los subsectores en el sector hidráulico. Sin embargo, el resultado contiene también subsectores que bordean el sector hidráulico. Aparentemente, la función Intersects devuelve los elementos que comparten el límite.

Para evitar esto, podemos aplicar un buffer negativo pequeño al polígono del sector hidráulico con el fin de solamente obtener los subsectores que están dentro del sector hidráulico (ver líneas 2 donde se aplique el buffer y la línea 3 donde se use el resultado):

var fs = FeatureSetByName($datastore,"Sub Sector");
var feature_buf = Buffer($feature, -100, 'meters');
var subsectores = Intersects(fs, feature_buf);
var cnt = Count(subsectores);

var resultado = "Listado de los " + cnt + " Subsectores:";
for (var subsector in subsectores) {
    resultado += TextFormatting.NewLine + subsector.IDSAP;
}

return resultado;

El resultado en la ventana emergente es así:

El listado no está ordenado y se ve mejor si podemos presentar la información ordenada. Esto se puede lograr con la función “OrderBy” (ver línea 3):

var fs = FeatureSetByName($datastore,"Sub Sector");
var feature_buf = Buffer($feature, -100, 'meters');
var subsectores = OrderBy(Intersects(fs, feature_buf), 'IDSAP ASC');
var cnt = Count(subsectores);

var resultado = "Listado de los " + cnt + " Subsectores:";
for (var subsector in subsectores) {
    resultado += TextFormatting.NewLine + subsector.IDSAP;
}

return resultado;

La ventana emergente ahora si muestre el listado ordenado:

Espero que este ejemplo les ayuda a entender lo que se puede hacer con las nuevas expresiones de Arcade.

OJO: Siempre es necesario validar el rendimiento del resultado de las expresiones. Es importante que la complejidad sea razonable con el fin de lograr un rendimiento aceptable para el usuario final.

Labels (1)
Comments

Hola Xander, muy buen articulo y bien explicado, me ha servido para mejorar un webmap en el que estoy trabajando y funciono perfecto.  te pregunto cuando creo mi un dashboard a partir de este webmap el identificador sigue traendo las expresiones en Arcade realizadas, pero si requiero hacer algo con estos campos con un gráfico circular por ejemplo ya estos campos no aparecen. supongo que esto sucede porque este va directamente al servicio o capa, conoces de alguna manera similar para hacer que estos campos funcionen con el dash?

gracias si me puedes ayudar. 

Hola Luis Felipe Vergara Solano ,

Primero que todo, me alegro que ha sido de utilidad este artículo y que has aplicado expresiones de Arcade para mejorar tu webmap. Lamentablemente, el soporte de Arcade en los tableros de control es limitado. Sin embargo, en un par de semanas va salir una versión nueva en beta del tablero de control basada en el JS API 4.x y la nueva versión se caracterice por su soporte y uso avanzada de Arcade para la configuración del tablero. 

En el video de lo nuevo en ArcGIS Online (actualización de anoche) a partir de minuto 5:57 muestre muy corto lo que viene para ArcGIS Dashboards Beta:

What's New in ArcGIS Online: March 2020 Update - YouTube 

... y se mencione este blog:

https://community.esri.com/community/gis/applications/arcgis-dashboards/blog/2020/03/06/introducing-... 

Version history
Revision #:
1 of 1
Last update:
‎12-18-2018 01:59 PM
Updated by:
 
Contributors