Pages

vendredi 25 février 2011

GPS garmin etrex venture HC /QGIS et Ubuntu 10.04

Afin de préparer une campagne d'échantillonnage terrain, j'ai eu a utiliser un GPS GARMIN etrex venture hc, sous ubuntu 10.04 équipé de QGIS 1.6. Suite aux nombreux problèmes rencontrés, je propose la solution que j'ai trouvé:

Tout d'abord, vous trouverez ici le forum qui m'a le plus aidé:


Installation des logiciels:
Dans un terminal tapez:

>sudo apt-get install gpsbabel
>sudo apt-get install gpsd
>sudo apt-get install Gebabbel
>sudo apt-get install viking

Afin de permettre la connection avec le GPS GARMIN:

>sudo gedit /etc/udev/rules.d/51-garmin.rules

Dans la fenêtre qui s'ouvre, tapez:

SYSFS{idVendor}=="091e", SYSFS{idProduct}=="0003", MODE="666"

Enregistrez et redémarrez

Communication avec le GPS
Utiliser viking pour communiquer avec le GPS: http://doc.ubuntu-fr.org/viking

Transformer SHP en GPX
Utiliser QGIS pour transformer une couche SHP (ShapeFile) en GPX (format d'échange GPX, utilisé par viking entre autre):
>charger couche shp dans qgis
>clic-droit sur la couche shp > sauvegarder sous ...
> choisir le format GPX
> sélectionner le système de projection WGS84 (EPSG: 4236)

Uploader votre GPX dans votre GPS GARMIN ETREx VENTURE HC

>ouvrir viking
>créer un "layer" GPS
>sélectionner le port USB dans "data preference" dans le fenetre qui s'ouvre
>menu>ouvrir> ouvrez votre fichier GPX: un nouveau "layer" apparaît
>sélectionnez les éléments à importer (waypoints, routes, tracks) et par glissé-déposé, ajoutez le dans le sous layer "émission " du layer GPS.
>clic droit sur layer GPS-> Emission vers le GPS.


En espérant vous avoir aidé !


jeudi 17 février 2011

[SpatiaLite] tirage aléatoire dans une base de donnée

Pour apprendre les bases de SpatiaLite, direction le cookbook en Francais: ici

Données:
- batiments (id, surface_sol, geometry) - type: polygon - + Index Spatial Rtree
- riviere (id, nomn geometry) - type: ligne -

Objectif: Tirer aléatoirement 5 batiments ayant une surface au sol > 100m² et situés à moins de 2500m du cours d'eau

Solution:
SELECT
a.*
FROM batiments as a
JOIN riviere as b ON (
ST_Distance(a.geometry,b.geometry)<=2500
AND
a.rowid IN (
SELECT pkid from idx_batiments_geometry
WHERE pkid MATCH RTreeintersects(
MBRminX(b.geometry)-2500,
MBRminY(b.geometry)-2500,
MBRmaxX(b.geometry)+2500,
MBRmaxY(b.geometry)+2500,
))
)

WHERE
a.surface>=100
ORDER BY random()
LIMIT 5

Quelques explications:
Requête SELECT ... FROM ... WHERE ... classique permettant de selectionner les bâtiments de plus de 100 m². La clause JOIN...ON... permet de joindre la table riviere, en filtrant uniquement les bâtiments situés à moins de 2500m d'un cours d'eau via st_distance(). Le code SQL en rouge , facultatif, utilise l'index spatial R*Tree de la table batiments afin de préfiltrer les batiments intersectant le MBR des cours d'eau, élargis de 2500 m, et ainsi améliorer la performance de la requête.
Le point le plus important ici réside dans l'utilisation de la fonction ORDER BY random() : ceci va permettre d'afficher les lignes du résultat dans un ordre aléatoire.
La clause LIMIT 5 permet de ne selectionner que les 5 premiers résultats.


L'association de GROUP BY random() et LIMIT x va permettre de simuler un tirage aléatoire de x lignes d'une table. Ceci est particulièrement intéréssant pour préparer des échantillonnages.
L'un des principaux avantages de réaliser le tirage aléatoire directement par SQL, est de pouvoir specifier des critères sur la population initiale.

Encore plus fort ....

Tentons maintenant de réaliser en une seule étape un échantillonnage stratifié.
Parmis les bâtiments situés à moins de 2500m d'un cours d'eau, je veux échantillonner:
- 5 batiments au hasard parmis les bâtiments de plus de 100 m² (>=100m²)
- 2 batiments au hasard parmis les bâtiments de moins de 100 m² (<100m²)

Solution:
SELECT id FROM
( ...requete précédente... )
UNION
SELECT id FROM
( ...requete précédente, en remplaçant >=100 par <100 et LIMIT 5 by LIMIT 2 ... )

La clause UNION va permettre de fusionner les résultats des deux requêtes. Ainsi, votre résultat se composera de l'id de l'ensemble des batiments à échantillonner.

jeudi 10 février 2011

tutoriel spatialite: pourcentage d'intersection

Objectif: determiner le pourcentage de recouvrement entre deux couches SIG

Données:
- table1 (geometry, id)
- table2 (geometry,id) + Index Spatial RTree

Méthode: on va calculer pour chaque objet de la table 1, l'aire (ou le pourcentage) d'intersection avec les objets de la table 2

Solution:
SELECT
table1.id as id1,
table2.id as id2
st_area( st_intersection(table1.geometry,table2.geometry) ) as "aire de recouvrement",
st_area( st_intersection(table1.geometry,table2.geometry) )/ st_area ( table1.geometry)
as "pourcentage de recouvrement"
FROM table1,table2
WHERE
st_intersects(table1.geometry,table2.geometry)
AND
table2.rowid IN (
SELECT pkid FROM idx_table2_geometry
WHERE pkid MATCH RTreeintersects(
MBRminX(table1.geometry),
MBRminY(table1.geometry),
MBRmaxX(table1.geometry),
MBRmaxY(table1.geometry),
)))

Quelques explications:
Clause SELECT ... FROM: on selectionne les colonnes voulues dans les tables.
- st_area(st_intersection()) calcule l'aire de l'intersection
Clause WHERE:
- jointure spatiale: la fonction st_intersects() permet de selectionner les objets des deux tables se chevauchants.
- RTree: Pour chaque objet de la table1, on préfiltre les objets de la table2 intersectant le RTree. Ceci permet d'accelerer grandement la requete

Facile non ?
En revanche, il est plus difficile de selectionner directement par SQL, pour chaque objet de la table 1, l'objet de la table 2 correspondant au recouvrement maximal (utile pour passer les valeurs d'une table dans une autre en fonction du taux de recouvrement). En effet, la clause GROUP BY id1 couplée à MAX(%intersecteion) va ici nous retourner des lignes composées de la façon suivante:
1) Une ligne par objet de la table 1
2) Pourcentage max de recouvrement entre cet objet et les objets de la table 2
3) un objet de la table2 "au hasard" (ne correspondant pas au taux de recouvrement maximal)

Objectif 2: Determiner pour chaque objet de la table 1, l'objet de la table 2 avec lequel le pourcentage de recouvrement est maximal

Solution:

Etape1:
Creer une vue à partir de la requete précédente ( vue = intermédiaire entre table et requete):
CREATE VIEW vue1 AS
SELECT ....requete précédente....

La vue1 contient alors la liste des pourcentages de recouvrement pour chaque couple d'objets (table1 et table2)

Etape2:
Creer une nouvelle vue contenant, pour chaque objet de la table1, la valeur max du pourcentage de recouvrement:
CREATE VIEW vue2 AS
SELECT
vue1.id1 as id1,
MAX( vue1."pourcentage de recouvrement" ) as "pourcentage de recouvrement max"
FROM vue1

Etape3:
Enfin, en utilisant les deux vues précédentes, il devient possible d'extraire de la vue1, les lignes correspondants au % max de recouvrement pour chacun des objets de la table1:
SELECT
*
FROM vue1
JOIN vue2 ON (
vue2.id1=vue1.id1
AND
vue2."pourcentage de recouvrement max"=vue1."pourcentage de recouvrement"
)

Et voila, le travail est terminé ! A priori cela peut paraître compliqué, mais en décortiquant un peu les requetes, on s'apperçoit que c'est à la portée de tout le monde.
De plus, répondre à ce genre de question via des logiciels SIG classiques (MAPINFO, QGIS, ...) s'avère encore plus complexe à mettre en oeuvre ...

Tutoriel SpatiaLite: distance minimale entre les objets de deux couches SIG

Pour ceux qui ne connaissent pas SpatiaLite, c'est ici que ça se passe:
http://www.gaia-gis.it/spatialite-2.4.0-4/spatialite-cookbook-fr/index.html

Données de départ:

- table1 (id,nom,geometry)
- table2 (id,nom,geometry) + Index Spatial R*Tree

Objectif: Pour chaque objet de la table1 , determiner la distance de l'objet le plus proche dans la table2 (dans la limite de 1Km, soit 1000m)

Contrainte: De manière intuitive, la solution serait toute simple:
SELECT
table1.nom as nom1,
table2.nom as nom2,
min(st_distance(table1.geometry,table2.geometry)) as distance
FROM table 1
JOIN table2 ON ( ....dist...)
GROUP BY 1
A priori, cette requete retourne effectivement pour chaque objet de la table1, la distance la plus courte le séparant des objets de la table2. Mais en regardant de plus près, pour chaque ligne l'objet de la table2 retourné par la requète correspond non pas à l'objet le plus proche, mais au premier objet trouvé... ceci est dû au fonctionnement même de GROUP BY. Afin de determiner les couples d'objets les plus proches, il faut ruser en passant par plusieurs étapes.

Solution: en plusieurs étapes

Etape 1: calcul des distances entre tous les couples possibles.
CREATE VIEW distances AS
SELECT
table1.nom as nom1,
table2.nom as nom2,
st_distance( table1.geometry,table2.geometry ) as distance
FROM table1
JOIN table2 ON (
st_distance( table1.geometry,table2.geometry )<=1000
AND table2.rowid IN (
SELECT pkid FROM idx_table2_geometry
WHERE pkid MATCH RTreeintersects(
MBRminX(table1.geometry)-1000,
MBRminY(table1.geometry)-1000,
MBRmaxX(table1.geometry)+1000,
MBRmaxY(table1.geometry)+1000
)))
GROUP BY 1

Analyse de la première étape:

Création d'une VUE ( que l'on pourra réutiliser dans les prochaines étapes - intermédiaire entre une table et une requete )
Requete du type SELECT.....FROM.... classique.
La fonction spatiale st_distance() permet de calculer la distance minimale entre chaque couple.
La sous-requete SELECT permet d'exploiter l'Index Spatial, en préfiltrant pour chaque objet de la table1, les objets de la table2 dont le MBR élargi de 1km intersecte le R*tree.

Etape 2: calcul de la distance minimale séparant chaque objet de la table 1 des objets de la table2

CREATE VIEW distances_min AS
SELECT
nom1 as nom1,
min( distance ) as "distance min"
FROM distances
GROUP BY 1

Analyse de la deuxième étape:

On crée une nouvelle vue à partir de la vue précédente (distances).
min(distance) et GROUP BY 1 vont permettre de selectionner pour chaque objet de la table1, la distance minimale le séparant des objets de la table2.

Etape 3: A chaque objet de la table1, nous associons l'objet de la table2 le plus proche

SELECT
distances.nom1 as nom1,
distances.nom2 as nom2,
distances.distance as distance
FROM distances
JOIN distances_min ON (
distances.nom1=distances_min.nom1
AND
distances.distance=distances_min."distance min"
)

Analyse de la dernière étape étape:
On va selectionner ( SELECT ... FROM ) les lignes de la VUE Distances.
Afin de récuperer, pour chaque objet de la table1, uniquement l'objet de la table2 le plus proche, on va JOINdre la vue distances_min.

Et voila, vous avez maintenant, pour chaque objet de la table 1:
- L'objet de la table 2 le plus proche
- La distance entre ces deux objets

mardi 8 février 2011

Utiliser Spatialite GUI avec Ubuntu 10.04

Le but de se post est de vous relater les petits soucis que j'ai eu pendant l'installation de spatialite-gui, l'interface graphique permettant de gerer les Bases de donnée SpatiaLite, sous ubuntu 10.04.
SpatiaLite est un SGBD spatial léger et nomade basé sur le célebrissime SQLite. Pour ceux qui ne le connaissent pas encore, voici quelques liens:
- http://www.gaia-gis.it/spatialite (site officiel, anglais)
- http://www.gaia-gis.it/spatialite-2.4.0-4/spatialite-cookbook/index.html (tutoriel, anglais)
- http://www.portailsig.org/content/sqlite-spatialite-le-pourquoi-du-comment (présentation en français)
Pour la procédure d'installation, il est très utile de consulter:
- http://www.gaia-gis.it/spatialite/install-linux.html


Pour utiliser spatialite, null besoin d'installer quoi que ce soit. Il suffit de telecharger spatialite-gui et de l'ouvrir.... A priori rien de plus simple.

Cependant, après le téléchargement, impossible de lancer ce programme...
J'essaye de le lancer via le terminal et j'obtiens une erreur indiquant qu'une "shared library" est manquante. (geotiff.so en l'occurence)
Apparement ce problème est fréquent avec ubuntu, car il rajoute la version des librairies au nom de celle ci ( ainsi, la librairie geotiff sera nommé geotiff.so.x.x au lieu de geotiff.so).

Pour résoudre ce problème, il existe deux solutions :

1.La plus simple et la plus rapide

Notez le nom exact de la librairie manquante: "somelib.so"
Verrifiez que cette librairie existe bien dans /usr/lib , sous un nom différent: "somelib.so.1"
Si la librairie existe, c'est tout simple: (si elle n'existe pas, il faudra la télécharger avant de continuer)
Dans un terminal, tapez:
cd /usr/lib
sudo ln -s somelib.so.1 somelib.so
Ce code va permettre de creer un lien symbolique vers la librairie, que spatialite-gui pourra utiliser.
Lancez à nouveau
SpatiaLite-gui , il devrait fonctionner correctement.
Si il ne se lance toujours pas, c'est peut-être qu'une deuxième librairie est manquante ( ca a été mon cas! ): il suffit dans ce cas de recommencer la procédure...



2.La plus radicale (et compliquée ): compiler les source

a) Verifier l'installation (en utilisant apt-get install ou synaptic)
des paquets suivants:
- libgeos-xxx
- libgeos-dev
- proj
- libjpeg-xxx
- libjpeg-dev
- libpng-xxx
- libpng-dev
- libtiff4
- libtiff4-dev
- libgeotiff
- libgeotiff-dev
- libcairo2
- libcairo2-dev
- libwxgtk-xx
- libvwgtk-xx-dev

b) Télécharger, extraire et installer libspatialite-amalgamation-2.4.0-rc4

Dans un terminal, se placer dans le dossier libspatialite-amalgamation...
./configure
make
sudo make install-strip

c) Télécharger, extraire et installer libgaiagraphics-0.4

Dans un terminal, se placer dans le dossier libgaiagraphics-0.4
export "CFLAGS=-I/usr/local/include/geotiff"
./configure
make
sudo make install-strip

d) Enfin, vous pouvez installer spatialite_gui-1.4.0
./configure
make
sudo make install-strip


Ca y est, spatialite-gui est installé ! Il suffit de cliquer sur le programme pour le lancer.

mercredi 2 février 2011

Automatiser les traitements sous GRASS: analyse réseau

Les manipulation suivantes sont valides pour ubuntu (testé sur 10.04).

Objectif: réaliser une analyse réseau (network analysis) automatiquement avec GRASS 6.x

Voici la procédure détaillée d'analyse réseau:

Comme vous le constatez, la procédure est assez longue. Heureusement, il est possible de l'automatiser en utilisant des scripts bash ( language utilisé par la console d'ubuntu).

Il est possible d'automatiser la procédure en lançant un script bash depuis la console linux et sans avoir à ouvrir GRASS, votre analyse réseau est effectuée !

- L'utilisation des script suivants implique que vous disposiez d'au moins une couche du réseau routier et d'une couche point chargés dans un mapset GRASS -

1/ Fichier "job.sh"
------------------------------------------------------------------------------------------
#!/bin/sh
# analyse reseau automatisée sous grass

#initialisation variables
echo -n "Entrez le nom de la couche reseau (routes) : "
read reseau
echo -n "Entrez le nom de la couche point : "
read point
echo -n "Entrez les iso-couts (ex: 100,1000,10000 m) : "
read couts
echo -n "Entrez le nom de la couche finale : "
read resultat

cat="0-99999"

#préparation analyse
#src: http://www.ing.unitn.it/~grass/docs/tutorial_64_en/htdocs/esercitazione/network_analysis/
v.net --overwrite --verbose input=$reseau points=$point output=network_tmp operation=connect thresh=500
v.db.connect -p map=network_tmp
v.db.connect -o --verbose map=network table=$point layer=2

#creation lignes de couts
v.net.iso --overwrite --verbose input=network_tmp output=$resultat ccats=$cat costs=$couts

#suppression_fichier_temporaire
g.remove vect=network_tmp
------------------------------------------------------------------------------------------

2/ préparez votre fichier "analyse_reseau.sh"
------------------------------------------------------------------------------------------
#!/bin/sh
# analyse reseau automatisée sous grass_lancement

echo " Script BASH: Réaliser une analyse reseau automatisée sous GRASS "
echo ""

echo -n "Entrez le nom de la région : "
read region
echo $region

echo -n "Entrez le nom du jeu de donnée : "
read dataset
echo $dataset


#permissions pour executer le script
chmod u+x ./bash_job.sh

export GRASS_BATCH_JOB=./bash_job.sh
grass "chemin vers votre dossier GRASS"/$region/$dataset/
unset GRASS_BATCH_JOB
------------------------------------------------------------------------------------------

Le premier fichier "job.sh" contient les instructions d'analyse GRASS.
Le fichier "analyse_reseau.sh" permet de programmer et lancer GRASS afin qu'il exécute les instructions contenues dans "job.sh". (il vous suffit simplement de personnaliser le code au niveau de "chemin vers votre dossier GRASS"

Pour lancer l'analyse, placez vous dans le répertoire contenant vos scripts:
> bash analyse_reseau.sh

L'analyse est éffectuée sous GRASS. Une fois terminée, GRASS se ferme, votre carte est prete.
Bien sur, il est possible de modifier, compléter ces scripts afin des adapter à vos besoins.


Meilleures ressources GRASS

GRASS est un logiciel SIG libre aussi puissant qu'il peut paraître complexe pour un débutant. Pourtant après quelques bonnes lectures, il est tout à fait possible de maîtriser la bete pour une utilisation courante.

Ce post est destiné à centraliser les meilleurs documents / tutoriels que j'ai pu rencontré au fil de mes recherches:

Documents classiques:
Tutoriel en français de GDF-hannover pour GRASS 6 html pdf
Grass 6 precis et concis html pdf

Petits bijoux du web:
Tutoriel GRASS de trento university (anglais) html zip(56 mo)
-> excellents tutoriels sur l'analyse réseau, et l'utilisation du visualisateur 3D (NVIZ)

Support ecw pour QGIS sous ubuntu

Sous ubuntu: (testé sur ubuntu 10.04 )

La prise en charge des formats d'images matricielles compressées ECW et JPEG 2000 n'est pas activé par défaut pour une question de licence.

Dans le terminal, copiez collez le code suivant:
sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable/ubuntu #On ajoute le dépôt
sudo apt-get update && sudo apt-get upgrade #On recharge et on met à jour la liste des paquets
sudo apt-get install gdal-bin libgdal-ecw-src #On installe gdal et le paquet libgdal-ecw-src

Ensuite, en fonction de votre version d'ubuntu, télécharger et installez le paquet suivant:
ubuntu 64 bits: ici et ici
ubuntu 32 bits: ici

Enfin, dans un terminal, tapez:
sudo gdal-ecw-build /usr

Pour verifier l'installation, la commande suivante doit afficher une liste contenant ecw et jp2ecw:
gdalinfo --formats | grep ECW

Maintenant, QGIS est capable d'ouvrir des fichiers ecw



Sous Windows:

Sous windows, le plus simple pour les non geek est de réinstaller une version de QGIS comportant le support ecw (vive ubuntu!).
La démarche est entièrement décrite sur le wiki de georezo.net: