Aumentar velocidad de carga de un mapfile utilizando simplificación de geometrías

En el anterior post creamos un mapfile dinámicamente con PHPMapScript, ahora lo que vamos a ver es como conseguir que la velocidad de carga de este mapfile se reduzca de forma considerable utilizando simplificación de geometrías mediante una función en PostGIS, esperando obtener un mapa con los municipios de toda España.

Resultado esperado:Mapa simplificado

El código de generación del mapfile será el mismo que en el  post de creación del mapfile “al vuelo”, tan solo habría que cambiar la forma de obtener los datos, para que en lugar de obtenerlos con una simple sentencia sql, llamar a una función que obtuviera las geometrías simplificadas a costa de perder nivel de detalle (inapreciable a la vista).

Cuando se trata de simplificar geometrías hay que tener en cuenta la dimensión del mapa que queremos obtener para en función de esta dimensión, poder obtener de alguna forma un coeficiente de simplificación que se adecue a la simplificación que pretendemos obtener (es decir, ni que no nos haga casi simplificación, ni que simplifique demasiado).

Para obtener este factor de simplificación, podemos hacer varias operaciones, en este caso realizaremos una operación como la siguiente, dividiremos el resultado de restar a la xmax la xmin de la entensión de la geometria entre el ancho del mapa que queremos obtener.

Es decir, obtenemos la extensión de la geometría que estamos analizando , sacamos al xmax y la xmin, las restamos y el resultado lo dividimos entre el ancho del mapa que queremos obtener:

(xmax(extent(geometria) )- xmin(extent(geometria)))/Ancho del mapa

Creamos una función en sql para obtener el factor de simplificación que deseamos:

create or replace function fs(float8) returns float8 AS $$
 select (xmax(extent(geometria))-xmin(extent(geometria)))/$1 from ine.municipios;
$$ LANGUAGE SQL;

Una vez que tenemos el factor de simplificación obtenido con la función anterior, ya podemos aplicar la simplificación con el factor de simplificación obtenido anteriormente.

Podemos hacer una comparativa del aumento de velocidad entre realizar una consulta sin simplificación y otra con la simplificación, por ejemplo para un mapa bastante grande de 4000px.

1ª consulta: “select geometria  from municipios2

2ª consulta:”select st_simplify(geometria,factor_simplificacion) from municipios2

En PostgreSQL, al ejecutar las dos sentencias podemos comparar y obtener:

1ª consulta

  • Tiempo de ejecución de la consulta: 50,84 segundos
  • Numero de vertices: 393666

2ª consulta

  • Tiempo de ejecución de la consulta: 19,51 segundos
  • Numero de vertices: 141610

De esta manera comprobamos que se produce un aumento en la velocidad a cambio de reducir el nivel de detalle, circunstancia que nos viene bien de cara a la publicación web, ya que no necesitamos un nivel de detalle elevado.

Para constaruir ahora la layer en MapScript, la sentencia SQL para obtener los datos sería como esta:

$name = $Layer2->set("name","Municipios");
$type = $Layer2->set("type",MS_LAYER_POLYGON);
$status = $Layer2->set("status",MS_ON);
//Conexión con nuestra base de datos que va as er de tipo POSTGIS
$Layer2->setConnectionType(MS_POSTGIS);
//Cadena de conexión a la base de datos donde tenemos nuestros datos

//En primer lugar, debemos obtener el factor de simplificación que obtenemos mediante consulta a postgresql desde php:
$conexion = pg_pconnect("host=localhost port=5432 dbname=demos user=postgres");

$sql="select fs(".$Map->width.")";
$resultado=pg_exec($conexion,$sql);
$factor=pg_result($resultado,0,0);

$Layer2->set("connection","user=postgres dbname=demos host=localhost");
//Filtro en sql que vamos a introducir para sacar nuestros datos a mostrar, aplicando el factor obtenido anteriormente
$data="geometria from (select st_simplify(geometria,".$factor.") as geometria, nombre,provincia,gid from municipios) as foo using SRID=23030, using unique gid";
$Layer2->set("data",$data);
//Una vez definida la estructura d ela capa procedemos a definir el estilo de nuestra capa número 1

Para la comparación de velocidad de creación de un mapfile con una única capa PostGIS utilizando una sentencia SQL normal y utilizando simplificación de geometrías, utilizando para ello varios test de medición de velocidad de carga, asumimos que vamos a crear un mapa bastante grande de una dimensión de 2000×2000 pixeles.

Sin simplificación de geometrías (tal y como se hizo en el artículo anterior, pero con una sola capa y de tamaño 2000×2000 píxeles)

Con simplificación de geometrías (utilizando la función que hemos programado anteriormente)

Para realizar la comparativa de cargas he utilizado la herramienta Speed-Test

El resultado que he obtenido es el siguiente:
(no se aprecia mucha diferencia, pero es debido a que se ha guardado en la caché y no es significativa la diferencia)
- Con la sentencia normal (sin simplificación)

URL: http://www.gisandchips.org/demos/mapscript/index_norm.php
Load Time: 1.048 seconds
Page Size: 0.19 kb

- Utilizando el factor de simplificación y realizando una simplificación de las geometrías:

URL: http://www.gisandchips.org/demos/mapscript/index_simp.php
Load Time: 1.013 seconds
Page Size: 0.18 kb
    • j3m
    • 6 noviembre 2009 4:01pm

    Enhorabuena por el artículo. Es muy interesante la aplicación de generalización cartográfica para acelerar el tráfico web.

    Tan sólo una recomendación: conviene utilizar las denominaciones de funciones que propone el propio portal de PostGIS, es decir, las “st_”, puesto que en futuras versiones puede desaparecer dejándo inútiles las aplicaciones.

    De esto:

    create or replace function fs(float8) returns float8 AS $$
    select (xmax(extent(geometria))-xmin(extent(geometria)))/$1 from municipios2;
    $$ LANGUAGE SQL;

    Habría que pasar a esto:

    create or replace function fs(float8) returns float8 AS $$
    select (st_xmax(st_extent(geometria))-st_xmin(st_extent(geometria)))/$1 from municipios2;
    $$ LANGUAGE SQL;

  1. Aun no hay enlaces.