Cómo crear una aplicación distribuida en amazon EC2 con Geoserver y Leaflet



En este Tutorial veremos cómo crear una aplicación distribuida para la información geográfica en amazon EC2 con Geoserver y Leaflet

1. Se ha comenzado instalando Geoserver en una instancia de Amazon EC2.

¿Qué es Geoserver?

GeoServer: Es un servidor de código abierto para compartir datos geoespaciales. Diseñado para la interoperabilidad, publica datos de cualquier fuente de datos espacial utilizando estándares abiertos.

He seguido el siguiente tutorial para realizar la instalación de Geoserver, inserto el enlace para no duplicar contenidos:

  • Cómo Instalar Geoserver

    En este Tutorial veremos cómo instalar Geoserver


Una vez finalizada la instalación de Geoserver se ha habilitado el firewall de Windows para permitir conexiones a Geoserver desde el exterior:

  • Como Habilitar el Firewall de Geoserver

    En este Tutorial veremos cómo habilitar el Firewall de Windows para permitir conexiones a Geoserver


Posteriormente se ha configurado en Amazon las "Inbound rules" de la instancia en la que hemos añadido una nueva regla que permita conexiones al puerto 8080 que es el puerto de Geoserver por defecto.

  • Cómo Habilitar Conexiones a Geoserver en Amazon AWS

    En este tutorial veremos cómo habilitar conexiones a Geoserver desde una instancia en Amazon AWS


Si hacemos una conexión a http://localhost:8080/geoserver/ desde la instancia o a http://TU IP:8080/geoserver/ podemos verificar que todo a salido correctamente.

2. Se ha Instalado la base de datos PostgreSQL 12 y la extensión de base de datos espacial PostGIS

¿Qué es PostgreSQL?

PostgreSQL: Es un sistema de gestión de bases de datos relacional orientado a objetos y de código abierto.

Para instalarlo he realizado el siguiente tutorial de cosecha propia:

  • Como Instalar PostgreSQL 12

    En este tutorial veremos cómo Instalar PostgreSQL 12, para posteriormente trabajar con la base de datos relacional


Para poder trabajar con datos espaciales ha sido necesario instalar la extensión PostGIS:

¿Qué es PostGIS?

PostGIS: Es una extensión de base de datos espacial para la base de datos relacional de objetos PostgreSQL.

Y el tutorial para realizar la instalación:

  • Como Instalar PostGIS 3.0

    En este Tutorial veremos cómo Instalar PostGIS 3.0 a través de la herramienta Stack Builder


Cuando se finaliza la instalación se nos da la posibilidad de crear una nueva base de datos espacial, he creado una llamada "ad4g".

Vamos a verificar que se ha creado correctamente la base de datos, para ello nos conectamos a través de la aplicación pgAdmin y nos abrirá en la instancia la url http://TU IP:53111/browser/

Se verifica que existe la base de datos llamada "ad4g", si nos vamos a extensiones verificamos que existen las siguientes extensiones de PostGIS: "postgis", "pointcloud_postgis", "postgis_raster"...

Creamos un nuevo Schema: "environmental" para trabajar con él y en el que posteriormente insertaremos nuestras capas espaciales.

Finalmente se ha configurado la conexión a PostgreSQL desde Geoserver, para ello se han seguido los siguientes pasos:

  1. Crear un Workspace, que le he llamado "AD4G".
  2. Añadir un nuevo store, u origen de datos, y he seleccionado Vector Data Sources - PostGIS - PostGIS Database
  3. Configurar la conexión a PostGIS seleccionando el Workspace: "AD4G", el nombre: "ad4g", el host: "localhost", el puerto: "5432", el schema: "environmental", el usuario y la contraseña.

3. Se ha Instalado QGIS y se ha realizado la conexión a PostGIS.

¿Qué es QGIS?

QGIS: Es un Sistema de Información Geográfica de código libre para plataformas GNU/Linux, Unix, Mac OS, Microsoft Windows y Android, creado y mantenido por una extensa comunidad de programadores y cuyo desarrollo es financiado mediante sponsors y donaciones.

Se ha realizado la instalación de QGIS 3.10.1 "A coruña" a través del instalador OSGeo4W.

Se ha Configurado la conexión a PostgreSQL desde QGIS en el que se ha configurado el nombre: "AD4G", el host: "localhost", el puerto: "5432", la base de datos: "ad4g" el usuario y la contraseña.


4. Se han descargado los datos espaciales y se han trabajado con QGIS.

Descargamos los datos de World's Protected Áreas en formato shapefile y la cargamos en QGIS.

Protected Planet es la fuente de información más actualizada y completa sobre áreas protegidas, actualizada mensualmente con presentaciones de gobiernos, organizaciones no gubernamentales, propietarios de tierras y comunidades. Es administrado por el Centro de Monitoreo de la Conservación Mundial del Medio Ambiente de las Naciones Unidas (PNUMA-WCMC) con el apoyo de la UICN y su Comisión Mundial de Áreas Protegidas (CMAP).

Es posible realizar una conexión WMS a un servidor ESRI a través de la url:

Pero he decidido realizar mi propio servicio WMS a través de Geoserver.

Como es una capa muy extensa y pesada, se ha realizado una selección en QGIS seleccionando la zona de estudio, que en mi caso me he decantado por las Islas Canarias y la isla de Madeira, posteriormente se ha subido la selección a la base de datos PostGIS al Schema creado anteriormente llamado "environmental" y le hemos llamado "Protected_Islas".

Recargamos en QGIS la conexión a la base de datos PostGIS llamada "AD4G" y Comprobamos que aparece la nueva tabla, para realizar dos verificaciones vamos a pgAdmin y Realizamos la siguiente consulta SQL:

           
                      
SELECT * FROM environmental."Proctected_Islas"
                      
                    

La consulta SQL nos devolverá 452 Registros.


Descargamos los datos ráster de TanDEM-X Mapa forestal a una resolución de 50 metros y descargamos la zona de estudio.

El mapa forestal / no forestal TanDEM-X es un proyecto desarrollado por el Instituto de microondas y radar en el Centro aeroespacial alemán (DLR), dentro de las actividades de la misión TanDEM-X. El objetivo es la derivación de un mosaico de clasificación global forestal / no forestal a partir de datos del radar de apertura sintética interferométrica biestática TanDEM-X (InSAR), adquiridos para la generación del modelo de elevación digital global (DEM) en el modo de polarización simple Stripmap (HH).

Se han descargado en total 16 ficheros .tiff:

           
                      
https://download.geoservice.dlr.de/FNF50/files/N30/W010/TDM_FNF_20_N30W017.zip
https://download.geoservice.dlr.de/FNF50/files/N30/W010/TDM_FNF_20_N30W016.zip
https://download.geoservice.dlr.de/FNF50/files/N29/W010/TDM_FNF_20_N29W014.zip
https://download.geoservice.dlr.de/FNF50/files/N28/W010/TDM_FNF_20_N28W014.zip
https://download.geoservice.dlr.de/FNF50/files/N28/W010/TDM_FNF_20_N28W015.zip
https://download.geoservice.dlr.de/FNF50/files/N28/W010/TDM_FNF_20_N28W016.zip
https://download.geoservice.dlr.de/FNF50/files/N27/W010/TDM_FNF_20_N27W016.zip
https://download.geoservice.dlr.de/FNF50/files/N27/W010/TDM_FNF_20_N27W017.zip
https://download.geoservice.dlr.de/FNF50/files/N28/W010/TDM_FNF_20_N28W017.zip
https://download.geoservice.dlr.de/FNF50/files/N28/W010/TDM_FNF_20_N28W018.zip
https://download.geoservice.dlr.de/FNF50/files/N27/W010/TDM_FNF_20_N27W018.zip
https://download.geoservice.dlr.de/FNF50/files/N27/W010/TDM_FNF_20_N27W019.zip
https://download.geoservice.dlr.de/FNF50/files/N28/W010/TDM_FNF_20_N28W019.zip
https://download.geoservice.dlr.de/FNF50/files/N32/W010/TDM_FNF_20_N32W018.zip
https://download.geoservice.dlr.de/FNF50/files/N32/W010/TDM_FNF_20_N32W017.zip
https://download.geoservice.dlr.de/FNF50/files/N33/W010/TDM_FNF_20_N33W017.zip
                      
                    

Cargamos los ficheros Ráster en QGIS y realizamos las siguientes operaciones:

  1. Combinamos todos los ficheros en uno con la función Combinar Ráster.
  2. Realizamos una reclasificación del Ráster, en el que he mantenido los valores pixel = 1 (que contienen los datos forestales) y he clasificado los demás valores como no data.
  3. Realizamos la operación poligonizar el Ráster Reclasificado.
  4. Una vez tengo los polígonos, como todos tienen los mismos valores, he realizado la operación Disolver para aligerar el peso de la capa.

Finalmente cargamos la capa llamada "bosques" en la base de datos de PostGIS "AD4G" en el Schema "environmental" y realizamos las oportunas comprobaciones como la capa anterior:

           
                      
SELECT * FROM environmental."Bosques"
                      
                    

5. Se han publicado las Capas espaciales en Geoserver.

Nos dirigimos a Geoserver y Añadimos una nueva Layer, seleccionamos el espacio de trabajo, Add layer from: "AD4G".

Añadimos las capas Bosques y Protected_Islas.

Para Jugar con los estilos de las capas de Geoserver, hemos añadido un estilo para cada capa:

Para la capa Protected_Islas he creado el estilo llamado "Protected", en el que le he aplicado una transparencia al relleno y le he dado el mismo tono verdoso al relleno y el borde.

           
                      
<PolygonSymbolizer>
<Fill>
  <CssParameter name="fill">#86db6b</CssParameter>
  <CssParameter name="fill-opacity">0.3</CssParameter>
</Fill>
<Stroke>
  <CssParameter name="stroke">#86db6b2</CssParameter>
  <CssParameter name="stroke-width">0.5</CssParameter>
</Stroke>
</PolygonSymbolizer>
                      
                    

Para la capa Bosques he creado el estilo llamado "green" en la que solo me he quedado con el relleno que le he dado un tono verde muy llamativo y he eliminado los bordes.

           
                      
<PolygonSymbolizer>
<Fill>
  <CssParameter name="fill">#66FF66</CssParameter>
</Fill>
</PolygonSymbolizer>
                      
                    

Para finalizar he publicado las capas, les he aplicado los estilos creados respectivamente y he definido los siguientes parametros, Coordinate Reference Systems: "EPSG:4326", Bounding Boxes: "Compute from data", Lat/Lon Bounding Box: "Compute from native bounds".

Comprobamos que Geoserver está sirviendo correctamente las capas como WMS en la instancia de Amazon:

Comprobamos que Geoserver está sirviendo correctamente las capas como WMS fuera de Amazon:


6. Se han cargado los Servicios WMS en QGIS y publicado como una Aplicación Web.

Realizamos una conexión WMS en qgis a las dos capas publicadas anteriormente.

Para agilizar el proceso y no escribir todo el código de 0 (que posteriormente he modificado), he instalado el plugin gratuito qgis2web.

qgis2web genera un mapa web a partir de su proyecto QGIS actual, ya sea como OpenLayers o Leaflet. Replica tantos aspectos del proyecto como sea posible, incluidas capas, estilos (incluidos categorizados y graduados) y extensión. No se requiere software del lado del servidor.

Se ha generado una Aplicacion Web con el cliente Ligero Leaflet.

¿Qué es Leaflet?

Leaflet: Es una biblioteca JavaScript opensource ampliamente utilizada para crear aplicaciones de Web Mapping.

Leaflet está diseñado teniendo en cuenta la simplicidad, el rendimiento y la usabilidad. Los mapas de Leaflet Funcionan de manera eficiente en todos los navegadores web.

He tomado como referencia mi tutorial:

  • Cómo crear un mapa básico con Leaflet

    En este tutorial veremos cómo crear un mapa básico con el cliente ligero Leaflet


Vamos a ver el código generado:

En esta parte declaramos la variable map, asignamos el BBOX y las atribucciones

           
                    
var map = L.map('map', {
    zoomControl:true, maxZoom:28, minZoom:1
}).fitBounds([[26.900577379622863,-18.548091967872697],[29.918933845916175,-13.963093568172635]]);
var hash = new L.Hash(map);
map.attributionControl.setPrefix('<a href="https://geopois.com/equipo" title="Javier Gabás">Javier Gabás</a> <a href="http://leafletjs.com" title="A JS library for interactive maps">Leaflet</a> <a href="https://carto.com/" title="Carto">Carto</a>');
var bounds_group = new L.featureGroup([]);
function setBounds() {
}                
					
                    

Para el mapa base, he importado un mapa de carto con unos colores muy atractivos que destaca por su simpleza.

           
                    
var layer_Cartodark_0 = L.tileLayer('https://cartocdn_{s}.global.ssl.fastly.net/base-flatblue/{z}/{x}/{y}.png', {
        opacity: 1.0,
        attribution: '',
    });
}   
map.addLayer(layer_Cartodark_0);      
                     
                    

Ahora vamos a ver las capas WMS publicadas en Geoserver:

           
                    

var layer_Proctected_Islas_1 = L.WMS.layer("http://54.80.197.162:8080/geoserver/AD4G/wms?", "Proctected_Islas", {
    format: 'image/png',
    uppercase: true,
    transparent: true,
    continuousWorld : true,
    tiled: true,
    info_format: 'text/html',
    opacity: 0.6,
    identify: false,
    attribution: 'Protectedplanet',
});              
map.addLayer(layer_Proctected_Islas_1);
                     
                    
           
                    
var layer_Bosques_2 = L.WMS.layer("http://54.80.197.162:8080/geoserver/AD4G/wms?", "Bosques", {
    format: 'image/png',
    uppercase: true,
    transparent: true,
    continuousWorld : true,
    tiled: true,
    info_format: 'text/html',
    opacity: 1,
    identify: false,
    attribution: 'EOC',
});
map.addLayer(layer_Bosques_2);   
                     
                    

Finalmente añadimos los controles a nuestro cliente ligero


7. Se han añadido capas en formato GeoJSON.

Como el servidor tarda bastante en servir las capas, he querido añadir alguna capa en formato GeoJSON.

En primer lugar me he descargado los datos de Especies protegidas del IDE de Canarias, además es posible descargarse un fichero de Simbología en formato QML de QGIS.

Mapa de especies protegidas generado a partir del Banco de Datos de Biodiversidad de Canarias por el Servicio de Biodiversidad de la Viceconsejería de Medio Ambiente.

El proceso ha sido:

  1. He cargado el fichero en Qgis y le he aplicado las simbologias.
  2. He exportado la capa con qgis2web.
  3. He integrado el código con el anterior.

El código resultante ha sido el siguiente:

           
                    
function pop_Especies_protegidas_0(feature, layer) {
    var popupContent = '<table>\
            <tr>\
                <td colspan="2">' + (feature.properties['n_especies'] !== null ? Autolinker.link(feature.properties['n_especies'].toLocaleString(), {truncate: {length: 30, location: 'smart'}}) : '') + '</td>\
            </tr>\
        </table>';
    layer.bindPopup(popupContent, {maxHeight: 400});
}

function style_Especies_protegidas_0_0(feature) {
    if (feature.properties['n_especies'] >= 1.000000 && feature.properties['n_especies'] <= 2.000000 ) {
        return {
        pane: 'pane_Especies_protegidas_0',
        opacity: 1,
        color: 'rgba(0,0,0,0.0)',
        dashArray: '',
        lineCap: 'butt',
        lineJoin: 'miter',
        weight: 1.0, 
        fill: true,
        fillOpacity: 1,
        fillColor: 'rgba(255,211,127,1.0)',
        interactive: true,
    }
    }
    if (feature.properties['n_especies'] >= 2.000000 && feature.properties['n_especies'] <= 5.000000 ) {
        return {
        pane: 'pane_Especies_protegidas_0',
        opacity: 1,
        color: 'rgba(0,0,0,0.0)',
        dashArray: '',
        lineCap: 'butt',
        lineJoin: 'miter',
        weight: 1.0, 
        fill: true,
        fillOpacity: 1,
        fillColor: 'rgba(255,170,0,1.0)',
        interactive: true,
    }
    }
    if (feature.properties['n_especies'] >= 5.000000 && feature.properties['n_especies'] <= 10.000000 ) {
        return {
        pane: 'pane_Especies_protegidas_0',
        opacity: 1,
        color: 'rgba(0,0,0,0.0)',
        dashArray: '',
        lineCap: 'butt',
        lineJoin: 'miter',
        weight: 1.0, 
        fill: true,
        fillOpacity: 1,
        fillColor: 'rgba(255,85,0,1.0)',
        interactive: true,
    }
    }
    if (feature.properties['n_especies'] >= 10.000000 && feature.properties['n_especies'] <= 100.000000 ) {
        return {
        pane: 'pane_Especies_protegidas_0',
        opacity: 1,
        color: 'rgba(0,0,0,0.0)',
        dashArray: '',
        lineCap: 'butt',
        lineJoin: 'miter',
        weight: 1.0, 
        fill: true,
        fillOpacity: 1,
        fillColor: 'rgba(230,0,0,1.0)',
        interactive: true,
        attribution: '<a href="https://opendata.sitcan.es/dataset/especies-protegidas" title="Especies Protegidas">Sitcan</a>'
    }
    }
}
map.createPane('pane_Especies_protegidas_0');
map.getPane('pane_Especies_protegidas_0').style.zIndex = 400;
map.getPane('pane_Especies_protegidas_0').style['mix-blend-mode'] = 'normal';
var layer_Especies_protegidas_0 = new L.geoJson(json_Especies_protegidas_0, {
    attribution: '',
    interactive: true,
    dataVar: 'json_Especies_protegidas_0',
    layerName: 'layer_Especies_protegidas_0',
    pane: 'pane_Especies_protegidas_0',
    onEachFeature: pop_Especies_protegidas_0,
    style: style_Especies_protegidas_0_0,
});
bounds_group.addLayer(layer_Especies_protegidas_0);
map.addLayer(layer_Especies_protegidas_0);  
                     
                    

8. Se ha conectado openrefine con PostgreSQL.

¿Qué es openrefine?

Open Refine: Es una herramienta creada por Google para la limpieza, arreglo y manejo de bases de datos. Fue desarrollado originalmente como "Freebase Gridworks" por Metaweb, está fue adquirida por Google en julio de 2010 y cambiaron el nombre del producto a Google Refine. En octubre de 2012, el producto pasó a llamarse OpenRefine a medida que pasaba a un proyecto respaldado por la comunidad (http://TU IP:3333/about.html).

Para iniciarlo ejecutamos la aplicación en la instancia y nos abrirá en el navegador: http://TU IP:3333/

Le damos a crear proyecto y nos permite elegir Base de Datos.

Configuramos la conexión a la Base de Datos PostgreSQL, Name: "127.0.0.1", Type: "PostgreSQL", Host: "localhost", Port: "5432", User: "tu usuario de postgres", Password: "tu contraseña de postgres", Database: "ad4g"

Probamos la conexión y el mensaje debería ser "Test Connection Succeeded!"

Le damos a conectar y vemos la url de conexión: "Connection :: jdbc:postgresql://localhost:5432/ad4g"

Openrefine nos permite realizar consultas en vivo sobre nuestra Base de Datos PostgreSQL, por ejemplo, realizamos la siguiente consulta SQL:

           
                      
SELECT * FROM environmental."Proctected_Islas"
                      
                    

Verificamos que se realiza la consulta satisfactoriamente y podemos visualizar los datos, a continuación, definimos el Project name: "ad4g" y creamos el proyecto.

Si nos dirigimos a Open Project, se verifica que se encuentra el proyecto y se puede trabajar.

           
                      
value.replace('State Verified','http://www.opengis.net/def/crs/EPSG/0/4326')
                      
                    

Una vez dentro del proyecto, he añadido la columna "crs" y he reconciliado la columna "name" con datos de dbpedia: "dbo:ProtectedArea" http://dbpedia.org/ontology/ProtectedArea.

Al tener una gran cantidad de datos y poca memoria RAM no he seguido con la reconciliación, solo quería probar que se podia conectar bases de datos a openrefine y cerrar el ciclo con las demás aplicaciones utilizadas a lo largo de la práctica, a modo teórico, después de acabar con las reconciliaciones exportaríamos la tabla como fichero RDF preparado para la web semántica y lo importaríamos a la Base de Datos Virtuoso.

Posteriormente realizariamos una conexión del siguiente tipo:

Y pasariamos el JSON a Leaflet como he realizado con la capa de "Especies Protegidas"

Y con esto terminamos este extenso tutorial en el que hemos hecho un repaso por las tecnologías y aplicaciones interesantes para crear una aplicación distribuida de la información geográfica.


¿Alguna pregunta? ¿Quieres realizar sinergias o colaboraciones? ¿Te gustaría enviarnos feedback sobre el tutorial? No dudes en contactar a jgabas@geopois.com.



Sobre el Autor


Javier Gabás Jiménez

Soy un apasionado de los mapas y la infraestructura de datos espaciales, me divierto mucho buscando formas de comprender y presentar datos visualmente, así como entender la programación que hay debajo. Ingeniero en geomática y topografía por la Universidad Politécnica de Madrid, cuando no estoy trabajando o estudiando, estaré viajando y disfrutando de la vida junto a mi pareja.



Formamos parte del programa de emprendimiento #17actuaupm