Automatisation QGIS des cartes dynamiques3D au moyen d'un script pyton
Objectif
l'automatisation de QGIS par des scripts pytrhon améliore sensiblement la vitesse d'exécution et évite les erreurs dûes aux tâches répétitives et fastidieuses. L'élaboration d'une carte 3D est réalisée manuellement en 5 mn avec un peu de pratique. Ce script va remplacer avantagement ces enchainements répétitifs et creer 5 cartes dynamiques couvrant les Alpes du Sud du Mercantour aux Ecrins en quelques secondes. Ces cartes pretes à lempoi sont utilisables par un simple lien sur le fichier de type "bassinFSCaaaammjj.HTML"
Principe
En prenant comme base le programme python Qgis2threejs export
Les commandes sucessives sont lancées a partir du panneau Python de Qgis qui par défaut initialise la variable iface, instance de QgisInterface.
Les enchainements suivants sont éxécutés
- Phase d'initialisation :importation du fichier des paramètres de reglage de Qgis2threejs,et desactivation de toutes les cartes FSC dans la liste des couches
- Chargement d'une carte FSC (fractional Snow Cover) au format TIF avec un systeme de projection WGS84 .Ces cartes proviennent du site cryoland. Elles sont stockées localement dans le répertoire QGis/FSC et renomées FSCaaaammjj.TIF
- Redimensionnement des bassin ( vesubie, ubaye ,tinéee Ubaye,Guil, Queyras, Ecrin) pour être entièrement contenu dans le canevas.Cette opération va modifier l'échelle de la carte en fonction de la fenêtre ecran disponible.
- Sauvegarde de l'écan au format JPEG après rafraîchissement complet des couches. Cette image nommée par convention "bassinFSCaaaammjj.JPEG" va remplacer avantageusement la carte base64 PNG calculée par Qgis2ThreeJs qui a pour principal inconvénient sa taille de 2 Mo
- Calcul des dimensions du canevas comme données d'entrée du script Qgis2ThreeJs.Exportation.
- Modifications dans le fichier FSCaaaammjj.JS elaboré par le script Qgis2ThreeJs. Remplacement de la portion de code "data:image/png;base64......." par l'adresse URI " bassinFSCaaaammjj.JPEG"
Detail du Fichier python FSC3D.py et commentaires
#modules d'importation
import os
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *
from Qgis2threejs.api import Exporter
#chargement du fichier FSC a partir du repertoire /home/knobuntu/QGis/FSC
#initialisation
#desactiver toutes les cartes FSC
for layer in QgsMapLayerRegistry.instance().mapLayers().values():
print layer
couchename= layer.name()
print couchename
x = couchename.find ('FSC')
if x >-1 :
iface.legendInterface().setLayerVisible(layer,False)
x=couchename .find('dem')
if x> -1:
iface.setActiveLayer(layer)
print couchename
#importation d'un FSC au format TIF
qfd=QFileDialog()
title='ouvrir un fichierraster FSC'
path="/home/knobuntu/QGis/FSC"
f=QFileDialog.getOpenFileName(qfd,title,path)
print f
liste=f.split('/')
inter=liste[-1]
liste=inter.split('.')
fscusuel=liste[0]
print fscusuel
layer= iface.addRasterLayer(f,fscusuel)
#chargement du fichier stylefsc.qml des distinction des couches de neige
layer.loadNamedStyle('/home/knobuntu/QGis/styles/stylefsc.qml')
layer.triggerRepaint()
# fichier de configuration dans /home/knobuntu/QGis/cryoland/config/config.qto3settings a reexporter lors de changements
settingsPath = "/home/knobuntu/QGis/cryoland/config/config.qto3settings"
#grandboucle
listebassin=['vesubie','tinee','ubaye']
for bassin in listebassin:
print bassin
# centrage et ajustement de la couche vectorielle 'bassin" dans la fenêtre de l'écran (canvas)
layer = QgsMapLayerRegistry.instance().mapLayersByName(bassin)[0]
layer.updateExtents()
canvas=iface.mapCanvas()
canvas.setExtent(layer.extent())
canvas.refresh()
w=QWidget()
info="Attendre le rafraichissement et le repositionnement sur "+ bassin
QMessageBox.information(w, "Rafraichissement en cours","attendre le rafraichissement complet des couches")
#mesures du canvas
canvas=iface.mapCanvas()
e= canvas.extent()
xmax=e.xMaximum()
xmin= e.xMinimum()
ymin=e.yMinimum()
ymax=e.yMaximum()
print xmax/2
centrex= xmin+(xmax-xmin)/2
centrey=ymin+(ymax-ymin)/2
etendueX=(xmax-xmin)
etendueY=(ymax-ymin)
xpixel=canvas.size().width()
ypixel=canvas.size().height()
#sauvegarde l image écran au format JPEG
couvertureUri="/home/knobuntu/QGis/cryoland/FSC3D/" + bassin + fscusuel +".jpeg"
canvas.saveAsImage( couvertureUri,None,"JPEG")
print couvertureUri
# tableau des lieux a exporter
places = [(bassin, QgsPoint(centrex,centrey))]
# fichier de sortie html par convention "Bassin + fscusuel+.html
path_tmpl = "/home/knobuntu/QGis/cryoland/FSC3D/" +bassin+fscusuel+ ".html"
print path_tmpl
# Coordonnees de transformation de wgs en lambert (non utilise lesysteme de reference est deja 2154)
wgs84 = QgsCoordinateReferenceSystem(2154, QgsCoordinateReferenceSystem.EpsgCrsId)
wgskno = QgsCoordinateReferenceSystem(2154, QgsCoordinateReferenceSystem.EpsgCrsId)
transform = QgsCoordinateTransform(wgskno,wgs84)
# Make sure that map canvas CRS is EPSG:2154
canvas = iface.mapCanvas()
canvas.setCrsTransformEnabled(True)
canvas.setDestinationCrs(wgskno)
# Get map settings from the map canvas
mapSettings = canvas.mapSettings()
# dimension du canvas
canvasSize = QSize(xpixel, ypixel)
mapSettings.setOutputSize(canvasSize)
# Etendue du canvas en coordonnees lambert pas de rotation
width = etendueX
height = etendueY
rotation = 0
# Creer et exporter
exporter = Exporter(iface, settingsPath)
exporter.setMapSettings(mapSettings)
for name, point in places:
# Coordinate transform
center = transform.transform(point)
# Set extent
exporter.setExtent(center, width, height, rotation)
# Output HTML file path
filepath = path_tmpl.format(name)
# Export
err = exporter.export(filepath, openBrowser=False)
if err == Exporter.NO_ERROR:
print "{0} has been exported to {1}".format(name, filepath)
else:
print "Failed to export {0}: {1}".format(name, err)
#remplacement du recouvrement PNG en base64 par le fichier "bassin+fscusuel+".JPEG"
fichier="/home/knobuntu/QGis/cryoland/FSC3D/"+bassin+fscusuel+".js"
ficsortie="/home/knobuntu/QGis/cryoland/sortie.js"
ficjs=open(fichier,'r')
ficsid=open(ficsortie,'w')
for ligne in ficjs:
x=0
print '1'
x=ligne.find ("data:image/png;base64")
if x>0 :
txt=ligne[:x]+bassin+fscusuel+'.jpeg"}'
ficsid.write(txt)
print 'trouve'
else:
ficsid.write(ligne)
ficjs.close()
ficsid.close()
os.rename(ficsortie,fichier)
#message e fin
QMessageBox.information(w, "Fin", "Les fichiers .HTML, .JS et .JPEG sont a transferer du repertoire local ../ QGis/cryoland/FSC3D vers le serveur ../images/cryoland/cartes3d" )