Faire des cartes d'analyse avec QGIS 1.3.0 et PostGIS 1.3🔗

Posted by Médéric Ribreux 🗓 In blog/ Qgis/

#gis #qgis

Introduction

Dans le monde des SIG libres, le choix des outils d'analyse est assez limité:

D'où la question: existe-t-il un moyen simple et efficace de représenter de l'information géographique travaillée et non brute de décoffrage ? Ma tentative de réponse vient à la suite de cet article… Pour faire simple, disons, que oui c'est possible avec un peu d'entraînement et surtout une bonne base de travail.

Le contexte de ce travail est d'utiliser uniquement QGIS et PostGIS pour afficher des cartes d'analyses. Une carte d'analyse est une carte qui croise de l'information géographique avec des données alphanumériques. Elles sont très utilisées en statistiques par exemple et en termes d'efficacité, avec un outil comme MapInfo Pro (utilisation des analyses thématiques) et des données correctes, ce genre de carte prend 15 minutes environ à créer.

Nous voulons effectuer des croisements d'informations simples. Par exemple, colorier une commune en fonction d'une valeur donnée. Cette valeur n'est pas située dans une table géographique mais dans une table simplement alphanumérique.

Les capacités de traitement de QGIS sont vraiment très limitées. On peut utiliser certains plugins genre ftools mais leur utilisation est assez complexe et surtout pas réservée à ce que nous voulons faire. En plus, ça ne fonctionne pas sur PostGIS. D'où l'idée d'utiliser les capacités de traitement de PostgreSQL et de PostGIS pour faire le travail. QGIS se contentera de l'affichage.

Tout est très simple…

logo PostGIS
logo PostGIS

logo QGIS
logo QGIS

Prérequis

Je suppose que vous avez QGIS (l'exemple fonctionne avec la version 1.3.0 sous Debian Squeeze, compilée à la main, car le paquet disponible sur gfoss.it est buggé) et un serveur PostgreSQL sous la main avec l'extension PostGIS. Si ce n'est pas le cas, Google est votre ami et il vous donnera des tonnes de sites qui expliquent comment on fait pour mettre en place l'infrastructure.

Pour simplifier le sujet serveur PostgreSQL, on va dire qu'il est situé sur localhost, que la base de données utilisée sera nommée "GEOBASE_LOCALE" et que l'utilisateur qgis a tous les droits dessus, y compris celui de créer des tables.

Je suppose aussi que vous disposez de l'outil ogr2ogr (pour le chargement des données).

Une modélisation light

Voyons maintenant ce que ça donne sur un exemple concret:

La table DEPARTEMENT est une table contenant le dessin géométrique des communes du département. Elle est composée des champs suivants:

La table UTILISATEUR_LINUX contient des informations alphanumériques sur les utilisateurs de GNU/Linux. Une ligne correspond non pas à une commune mais à un utilisateur.

Pour chaque ligne, on a les champs suivants:

Le lien entre la table géographique et la table alphanumérique est le code INSEE (champ INSEE dans les deux tables).

Pour la table UTILISATEUR_LINUX, on aurait pu choisir un modèle plus simple (genre une ligne par commune) mais le modèle de cette table va nous permettre de faire quelques agrégations… Ça ne fait jamais de mal de voir ce qu'on peut faire comme calculs avec un peu de SQL.

Au final, nous allons créer une table géographique nommée LINUX qui contiendra les objets géographiques et les données alphanumériques qui nous intéressent à savoir:

Récupérer les données

Pour les données géographiques, j'ai utilisé la couche GEOFLA des départements produite par l'IGN. Ces données sont non libres (pas d'exploitation commerciale) mais gratuites au format Shapefile (lien pour les télécharger) . Je vous conseille de télécharger dans la projection RGF93 car la suite des manipulations utilise cette projection.

Les données sont au format shapefile. Il faut donc les convertir et les charger dans le serveur PostGIS, ce que nous allons faire avec shp2pgsql comme suit:

shp2pgsql -s 2154 -d DEPARTEMENT DEPARTEMENT | psql -h localhost -U qgis -W GEOBASE_LOCALE

L'option -s 2154 permet de spécifier la projection (2154 correspond à RGF93) et -d permet d'effacer la table si elle existe déjà.

Pour les données de la table UTILISATEUR_LINUX, j'ai créé une table remplie avec des valeurs aléatoires dont vous pouvez disposer ici. Il s'agit d'un script SQL contenant des valeurs aléatoires. Pour injecter les données, il suffit de faire:

psql -h localhost -U qgis -W GEOBASE_LOCALE -f UTILISATEUR_LINUX.sql

Quelques précautions techniques

Avant de créer une table géographique, il ne faut pas oublier que QGIS impose certaines règles lors de la création de tables. D'abord, pour que QGIS liste la table LINUX, il est indispensable que les colonnes géographiques soient renseignées dans la table "geometry_columns". C'est le comportement normal de PostGIS aussi, mais pas de PostgreSQL. L'ajout de cette information dans la table peut être effectué de deux manières. La technique utilisée est l'emploi de la requête suivante:

De plus, QGIS exige que la table dispose d'un champ d'identification qui doit être de type int et disposer d'une contrainte de clef unique. Enfin, QGIS travaille avec des valeurs plutôt en réel (float8) qu'en entier (integer). Cette contrainte impose que les résultats de requête soient convertis avant de pouvoir travailler avec.

Créer une couche avec des valeurs de référence et une donnée géographique

L'objectif est de créer une couche en utilisant une jointure pour lier un objet géographique à une ou plusieurs valeurs. Ensuite, on utilisera QGIS pour affecter la couleur et gérer les classes.

Cette requête permet de créer la table géographique LINUX en croisant les données géographiques de la table DEPARTEMENT et les données alphanumériques de la table UTILISATEUR_LINUX en effectuant une agrégation d'informations (Nombre d'utilisateurs, nombre de machines, densité d'utilisateurs et densité de machines). Cette couche répond aux exigences de QGIS.

Visualiser le résultat

Le travail est centré sur les onglets de propriétés de la couche dans QGIS:

C'est dans cet onglet que l'on peut régler la représentation de la couche. QGIS nous propose 4 modes de représentation:

densités réglages
densités réglages

Dans notre cas, seules les densités sont représentables avec les objets surfaciques des départements. Nous allons donc utiliser le symbole gradué. La représentation qui utilise ce mode est très intéressante dans QGIS car elle permet de créer des classes de manière assez simple:

Voici ce qu'on obtient:

Densité Linux
Densité Linux

Créer une carte avec des points de couleur

Le principe est le même que précédemment. Toutefois, au lieu de prendre l'objet géographique, on va utiliser son centroïde pour y positionner un symbole. Nous allons donc avoir besoin de la fonction PostGIS: ST_Centroid().

Cette requête permet de créer quasiment la même table qu'auparavant mais génère des points et non des surfaces. Pour faire une carte digne de ce nom, il convient d'utiliser également les surfaces, histoire d'améliorer le support visuel. On a donc intérêt à ouvrir les couches LINUX_POINT et LINUX (ordre des calques également). La couche LINUX sert uniquement de fond de carte, on va donc l'ouvrir et choisir une couleur neutre.

Travaillons maintenant sur la couche LINUX_POINT:

nombre de réglages
nombre de réglages

Voici le résultat final:

Nombre de machines Linux
Nombre de machines Linux

Utiliser des vues

Notre mode opératoire permet de publier assez rapidement des cartes. Toutefois, si les données de la table UTILISATEUR_LINUX changent, il faut supprimer les couches (par la requête SELECT dropgeometrytable('COUCHE')) et relancer les requêtes de croisement. Cela peut se révéler assez fastidieux si la table change régulièrement. Heureusement, PostgreSQL peut nous aider grâce à son concept de vue: une vue est une requête SELECT qui se lance à chaque fois qu'on interroge la vue. Donc si la requête est longue, le résultat met du temps à s'afficher.

Pour utiliser des vues, il suffit d'employer le terme CREATE VIEW au lieu de CREATE TABLE dans les requêtes de croisement d'information. L'intérêt des vues c'est que l'on ne stocke rien en dur et que les données sont toujours à jour par rapport à la table de référence. Le plus important est bien d'affecter la colonne géométrie dans la table de référence.

Si on utilise ensuite QGIS, on ne verra aucune différence: la table est présente et rien n'indique que c'est une vue. En revanche, le premier affichage est plus long: c'est à ce moment que la requête est lancée. Dans notre cas, c'est assez rapide tout de même.

Une idée: "Travailler avec des tables temporaires" ?

PostgreSQL supporte le concept de tables temporaires. Toutefois, ces dernières se suppriment automatiquement à la fin du pool de requête. Je n'ai pas trouvé comment les utiliser concrètement. Les vues me semblent mieux adaptées à notre objectif.

Références: