banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Rencontres QGIS 2025

L'appel à participation est ouvert jusqu'au 19 janvier 2025!

#1 Thu 05 March 2015 12:09

simeric
Participant assidu
Date d'inscription: 10 Mar 2009
Messages: 255

QGIS : Export KML avec information temporelle "TimeSpan"

Bonjour
Quelqu'un aurait-il une astuce pour exporter des données depuis Qgis en KML en enregistrant des infos temporelles dans la balise spécifique "TimeSpan" (afin que l'info soit exploitable dans la barre temporelle de Google Earth) ?
..ou bien un outil libre permettant de faire ça à partir d'un shapefile ?
Merci

Hors ligne

 

#2 Thu 05 March 2015 23:38

gvellut
Participant actif
Lieu: Annecy
Date d'inscription: 13 Apr 2006
Messages: 112
Site web

Re: QGIS : Export KML avec information temporelle "TimeSpan"

Si tu connais Python, tu pourrais créer un plugin. J'ai déjà eu il y a quelques temps à exporter un projet QGIS en KML un peu spécifique donc si tu le souhaites je peux te fournir un bout de code que tu pourrais customiser (notamment l'ajout de la balise TimeSpan).

Hors ligne

 

#3 Fri 06 March 2015 09:38

simeric
Participant assidu
Date d'inscription: 10 Mar 2009
Messages: 255

Re: QGIS : Export KML avec information temporelle "TimeSpan"

avec plaisir !
Je pense que ça peut intéresser la communauté.

Hors ligne

 

#4 Fri 06 March 2015 11:40

gvellut
Participant actif
Lieu: Annecy
Date d'inscription: 13 Apr 2006
Messages: 112
Site web

Re: QGIS : Export KML avec information temporelle "TimeSpan"

Voici une classe (adaptée de mon projet). J'espère que ça peut t'aider.

Code:

from qgis.core import *
from qgis.gui import *

import logging
logging.getLogger('fastkml.config').addHandler(logging.NullHandler())
from fastkml import kml

import shapely.wkt
import os
import re
import zipfile
from xml.etree import ElementTree

class KmlExport(object):
    def __init__(self):
        self.ns='{http://www.opengis.net/kml/2.2}'
        ElementTree.register_namespace('',"http://www.opengis.net/kml/2.2")
        
            
    def projectToKml(self, projectId, outputDirectory, prettyprint=False):
        
        root=QgsProject.instance().layerTreeRoot()
        k = kml.KML()
        d = kml.Document(self.ns, projectId, projectId)
        k.append(d)
        
        self._addLayersInFolder(root, d, "")
        
        self._outputToKmlAndKmz(outputDirectory, k, projectId, prettyprint)

    def _addLayersInFolder(self,folder,kmlContainer, baseName):
        for node in folder.children():
            if QgsLayerTree.isGroup(node):
                folderName=node.name()
                folderName=baseName+folderName
                f = kml.Folder(self.ns, folderName, folderName)
                kmlContainer.append(f)
                self._addLayersInFolder(node, f, folderName+"_")
            else:
                layerName=node.layerName()
                layerName=baseName+layerName
                f = kml.Folder(self.ns, layerName, layerName)
                kmlContainer.append(f)
                self._addFeaturesInLayer(node.layer(), f)
                
    def _addFeaturesInLayer(self, layer, kmlContainer):
        nameField=self._nameField(layer.name())
        idLayer="#%s"%self._toId(layer.name())

        fieldNames=map(lambda x:x.name(),layer.dataProvider().fields().toList())
        nameFieldIndex=layer.fieldNameIndex(nameField)
        for feature in layer.getFeatures():
            try:
                attributes=feature.attributes()
                geometry=feature.geometry()
                if not geometry:
                    qDebug("Invalid geometry in layer %s (id='%s',geometry='%s')"%(layer.name(),
                                            attributes[nameFieldIndex],geometry.exportToWkt()))
                    continue
                
                p=kml.Placemark(self.ns)
                p.name=attributes[nameFieldIndex]
                p.geometry=shapely.wkt.loads(geometry.exportToWkt())
                data=self._dataElementsFromAttributes(fieldNames,attributes )
                if len(data) > 0:
                    p.extended_data = kml.ExtendedData(self.ns, [kml.SchemaData(self.ns, idLayer, data)])
                kmlContainer.append(p)
            except Exception:
                qDebug("Error in layer %s (id='%s',geometry='%s')"%(layer.name(),
                                                                    attributes[nameFieldIndex],geometry.exportToWkt()))
                raise
            
            
    def _outputToKmlAndKmz(self, outputDirectory, kmlData, base, prettyprint):
        if prettyprint:
            # etree does not support prettyprint. Do it ourselves
            content=self._prettyPrint(kmlData.etree_element())
        else:
            content=kmlData.to_string().encode('utf-8')
        kmlFileName=base+".kml"
        with open(os.path.join(outputDirectory,kmlFileName),"wb") as f:
            f.write(content)
            
        kmzFileName=base+".kmz"
        with zipfile.ZipFile(os.path.join(outputDirectory,kmzFileName), 'w', zipfile.ZIP_DEFLATED) as kmz:
            kmz.writestr("content.kml", content)
        
    def _nameField(layerName):
        # FIXME add some logic
        return "ID"
        
    def _dataElementsFromAttributes(self, fieldNames, attributes, removeNullValues=False):
        data=zip(fieldNames,attributes)
        if removeNullValues:
            data=filter(lambda x:x[1] <> None, data)
        return map(lambda x:(x[0], self._toKmlValue(x[1])),data)
    
    def _toKmlValue(self, value):
        if isinstance(value, str) or isinstance(value, unicode):
            return value
        else:
            return str(value)

    def _toId(self, name):
        return re.sub(r'[^a-zA-Z_0-9\-]','_',name)
    
    def _prettyPrint(self, elem):
        self._indent(elem)
        return ElementTree.tostring(elem,"utf-8")

    def _indent(self,elem, level=0):
        i = "\n" + level*"  "
        if len(elem):
            if not elem.text or not elem.text.strip():
                elem.text = i + "  "
            if not elem.tail or not elem.tail.strip():
                elem.tail = i
            for elem in elem:
                self._indent(elem, level+1)
            if not elem.tail or not elem.tail.strip():
                elem.tail = i
        else:
            if level and (not elem.tail or not elem.tail.strip()):
                elem.tail = i

Il faut installer les librairies Python fastkml et pygeoif.

Quand projectToKml est appelée (par exemple depuis un plugin QGIS), les couches du projet QGIS sont parcourues et une arborescence KML correspondante est créée avec les objets de chaque couche. Finalement un KML et un KMZ sont exportés.  Une limitation du code ci-dessus est que le style de la couche n'est pas exporté (juste les données) donc si c'est important pour toi c'est qqch de plus à modifier.

Pour ton besoin, une fois que tu as un Placemark, tu peux utiliser placemark.begin et placemark.end pour setter le TimeSpan.

Dernière modification par gvellut (Fri 06 March 2015 11:52)

Hors ligne

 

#5 Fri 06 March 2015 11:41

simeric
Participant assidu
Date d'inscription: 10 Mar 2009
Messages: 255

Re: QGIS : Export KML avec information temporelle "TimeSpan"

merci !

Hors ligne

 

Pied de page des forums

Powered by FluxBB