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.
Considere que contamos con un mapa con 3 capas y una tabla:
En este ejercicio queremos hacer lo siguiente:
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.
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:
El resultado presentamos en una ventana emergente donde hacemos uso de una “visualización de atributos personalizado”:
Al usuario final se ve así:
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:
El resultado se veré así:
En este ejemplo tenemos 93 hidrantes en el subsector y la edad media es de 20,64 años.
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.
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: