archivo

Archivo de la etiqueta: script

linexyEl otro día un compañero en las listas de usuarios de gvsig de nos planteó una necesidad que tenía: añadir a la tabla de datos 4 campos nuevos que contuvieran las coordenadas X, Y de inicio y fin de las lineas que tenía su shape.

La solución sin usar programación la podéis seguir en dos emails[1] [2], explicada gracias a Gustavo Agüero Córdoba . 

Me parecía un buen ejemplo sencillo para exponer y aquí lo tenéis, simplemente tenéis que tener la capa activa donde queréis realizar los cambios,  y ejecutarlo. Sencillo pero que te puede ser muy útil, o servirte de base para algo que utilices.

import gvsig
from geom import *

def main():
    """Obtiene los vertices finales de 
        lineas y los agrega a tabla"""
    #Nuevo nombre para los campos X,Y
    campoX = "X_final"
    campoY = "Y_final"
    campoXi = "X_inicial"
    campoYi = "Y_inicial"
    layer = gvsig.currentLayer()
    
    schema = layer.getSchema()
    schema.modify()
    schema.append(campoXi,"DOUBLE", 30)
    schema.append(campoYi,"DOUBLE", 30)
    schema.append(campoX, "DOUBLE", 30)
    schema.append(campoY, "DOUBLE", 30)
    layer.edit()
    layer.updateSchema(schema)
    layer.commit()
    features = layer.features()
    for line in features:
        geom = line.geometry()
        vertex = geom.getVertex((geom.numVertices-1))
        vertexi = geom.getVertex(0)
        x,y = vertex.getX(), vertex.getY()
        xi,yi = vertexi.getX(), vertexi.getY()
        line.edit()
        line.set(campoX, x)
        line.set(campoY, y)
        line.set(campoXi, xi)
        line.set(campoYi, yi)
        layer.update(line)
        
    layer.commit()

 

leafgvsigEste post es un pequeño ejemplo de algunas funcionalidades extra que le podemos dar a nuestro módulo de Scripting en gvSIG 2, en este caso crear un visor web con solo un click. Pero primero de todo decir que el script ni esta perfecto ni pretende estarlo, solo quiero demostrar posibles nuevos usos de este módulo y animaros a probar cosas nuevas.

gvsig2leaflet viene de la idea del post que salió recientemente sobre qgis2leaflet un plugin (mucho más completo) para QGIS, pero en un rato que tuve libre quería demostrar que esto también es posible desde gvSIG 2 y directamente con el módulo de Scripting.

leafgvsig3

Carpeta visor Leaflet

Actualmente lo que hace es, desde una vista donde las capas estén en WGS84 y una capa de polígonos(polígonos simples, el problema es que aún no dispongo de un exportador a geojson completo desde scripting) que tengamos activa (con o sin selección), nos genera en una carpeta (que configuramos en las primeras lineas de código) con un archivo index.html (visor de Leaflet) y una carpeta dentro con el archivo js/geojson.js que contendrá los datos vectoriales de nuestros polígonos en formato geojson, pero preparados para ser usado en Leaflet. Hay alguna funcionalidad básica añadida, si modificáis la linea 55 podéis cambiar las propiedades de vuestros polígonos que muestran los popup al hacer click.

En un click

En un click

El resultado es una carpeta con un visor que podéis abrir o subir a vuestro host y visualizar vuestros datos. La podéis abrir directamente en cualquier navegador.

Ejemplo de uso

Ejemplo de uso

Añadir más funcionalidades, o exportar diferentes capas a la vez, añadir menus o estilos, sería cuestión de ponerse y programar, pero la posibilidad de hacerlo esta ahí, solo quería demostrar que hay más cosas posibles desde este módulo.

from gvsig import *
import os

def main(*args):

    global pathGeojson
    global pathHtml
    global path

    path = "C:/gvsig/geojson/leaflet/"
    pathGeojson = path + "js/geojson.js"
    pathHtml = path + "index.html"

    directorio = os.path.join(path, 'js')
    if not os.path.isdir(directorio): os.mkdir(directorio)

    f1 = open(pathHtml,"wb")
    layer = currentLayer()
    exportLayer(layer)

    f1.write("""
    <!DOCTYPE html>

    <html>
    <head>
        <title>Prueba</title>
        <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" />
        <script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script>
        <script type="text/javascript" src="js/geojson.js"></script>
    </head>

    <body>
    <div id="map"></div>

    <div id="map-div"></div>

    <style>
        #map { height: 600px; }
    </style>

    """)

    f1.write("""
    <script>

    var map = L.map('map').setView([%s, %s], 5);
        L.tileLayer('http://a.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
        minZoom: 3,
        maxZoom: 15,
        tms: false
        }).addTo(map);

    function onEachFeature(feature, layer) {
        layer.bindPopup(feature.properties.NAME);
    }

    L.geoJson(geojsonFeature, {
    onEachFeature: onEachFeature
    }).addTo(map);

    </script>
    </body>
    </html>
    """ % (40,3))
    f1.close()

def exportLayer(layer):
    #features o seleccion
    if layer.getSelection().getCount() == 0:
        selection = layer.features()
    else:
        selection = layer.getSelection()
    exportFeatureCollection(selection)

def exportFeatureCollection(selection):
    print "Export Feature Collection"
    f = open(pathGeojson,"wb")
    f.write(""" var geojsonFeature = {
    "type": "FeatureCollection",
    "features": [
    """
    )
    listVert = []
    typeGeom = ""
    count=0
    end= selection.getCount()

    for sel in selection:
      geom = sel.geometry()
      listVert, typeGeom = exportGeom(geom)
      #todos los atributos a una lista de properties:
      dic =  sel.getValues()
      properties = []
      for di in dic:
        try:
            value = str(di)
        except:
            value = "field1"
        try:
            value2 = str(dic[di])
        except:
            value2 = "row2"

        properties.append([value,value2])
      writeFeatureCollection(listVert, typeGeom, properties, f)
      count +=1
      if not(count == end): f.write(",")

    f.write("""
    ]
    };
    """
    )
    f.close()

def writeFeatureCollection(listVert, typeGeom, properties, f):
    tipo = '"'+str(typeGeom)+'"'

    f.write( """
    {
    "type": "Feature",
      "properties": {
      """)
    end = len(properties)
    start = 0
    for prop in properties:
            prop1 = '"'+str(prop[0])+'"'
            prop2 = '"'+str(prop[1])+'"'
            stri = str(prop1) + ":" + str(prop2)
            f.write(stri)
            start += 1
            if not(start == end): f.write(",")

    f.write( """
      },
      "geometry": {
        "type": """+ tipo +""" ,
        "coordinates": [ """ +
    str(listVert) +
    """
    ]
    }
    }
    """ )

def exportGeom(geom):
    print "geometria: ", geom
    if str(geom) == "Surface2D":
        typeGeom = "Polygon"
        vert = geom.getNumVertices()
        listVert = []
        for i in range(0, vert):
            x = geom.getVertex(i).getX()
            y = geom.getVertex(i).getY()
            listVert.append([x,y])

        x = geom.getVertex(0).getX()
        y = geom.getVertex(0).getY()
        listVert.append([x,y])
    return listVert, typeGeom

Espero animaros a que creéis vuestros propios scripts, y si veo la gente animada, me comprometo a acabar mejorando este script para que sea mucho más completo.

Un saludo

qgis01Sigo haciendo pruebas con PyQGIS, este sería el cuarto post sobre este tema, explicando poco a poco como programar para diversos programas SIG paso a paso.

Os voy a enseñar un pequeño código que explica como acceder a las entidades de una forma muy sencilla. Tan solo necesitáis tener abierto QGIS, con una capa de tipo polígono (para poder usar la función área) y ya podréis ejecutarlo.

·

Si quieres ponerte al día aún puedes consultar mis otros post:

from qgis.core import *

#Capa activa
vl = qgis.utils.iface.mapCanvas().currentLayer() 

#Entidades
iter = layer.getFeatures()

for feature in iter:
    #Indice del campo
    idx = layer.fieldNameIndex("PARQUES_ID")

    #id, nombre, area
    print int(feature.attributes()[idx]),
    print feature.attributes()[4],
    print feature.geometry().area()

pyqgis-entidades01

webinar-scriptingVoy a explicar dos de los ejemplos que puse ayer durante el webinar y animaros a probar el módulo de Scripting.

Si os perdisteis el webinar de ayer puedes ver aquí las diapositivas que use y podéis preguntarme cualquier duda por email, sobre el webinar y sobre el “Curso de Scripting en gvSIG 2” que anunciamos durante el mismo. Gracias a todos los que asististeis y a la plataforma de MundoGEO, pronto estará subido el vídeo del webinar.

Podéis ver ya el vídeo en Youtube.

 

Instalación

Sin títuloPara hacer el ejemplo y empezar con esto, debéis tener instalado gvSIG 2, os recomiendo que cojáis la última versión posible, justo ayer salio la primera realease candidate, gvSIG 2.1 RC1, que te puedes descargar en el siguiente enlaceUna vez instalada o durante la instalación, deberéis  acceder al Administrador de complementos desde el menú de Herramientas e instalar el “Scripting Framework”, ahora cuando abráis gvSIG  os saldrá dentro de Herramientas el menú de Scripting.

Si andas aún un poco perdido, en estos dos post lo explico mejor: Guía de Instalación y Tu primer script

Ejemplos

Ahora podréis usar el módulo de scripting y os voy a explicar como realizar un pequeño ejemplo. Vamos a crear una Vista nueva en nuestro proyecto, y vamos a agregar dos capas (he preparado un pack con los datos que utilice y os los podéis descargar aquí), una capa de puntos y otra de municipios.

A continuación accedemos a Herramientas – Scripting – Scripting composer. Creamos un nuevo script dándole a la hoja en blanco de arriba a la izquierda, le ponemos un nombre al script y OK. En este script en blanco deberemos pegar el siguiente código desde el Repositorio de Scripts. Os recuerdo que cualquiera estáis invitados a participar en este repositorio introduciendo los scripts que creéis para compartirlos con el resto de usuarios. Este código lo que va a hacer es coger una capa de puntos y unirlos todos en el orden que aparezcan en una línea y crear una capa nueva con esta línea.

webinar-scripting2

Líneas que modificar

Copiamos y pegamos este código en nuestro script nuevo, tan solo deberéis de cambiar dos lineas, una que empieza por nameLayer,que dará el nombre a la capa, y otra path que indicará donde grabar la capa nueva.

TIP: Para que el script funcione, la capa no debe de existir en el directorio, así que si lanzáis varias veces el script y os da un fallo del tipo “Can’t finish layer edition“, suele ser porque la ruta no existe o la capa ya existe.

Antes de ejecutarlo, tendréis que tener seleccionada la capa de puntos en vuestra Vista, tiene que aparecer en negrita tan solo haciéndole click. Esto es porque el script cuenta con la función currentLayer(), que cogerá los datos de la capa activa. Si le damos a Guardar y luego al botón de la rueda Ejecutar, lanzaremos nuestro script y veremos como nos aparece una capa nueva en nuestra Vista con el nombre que le habéis dicho anteriormente.

webinar-scripting3

Una vez tengamos esta capa, lo que vamos a hacer con el siguiente script será hacer una selección de todos los municipios por los que pasa la ruta de puntos. Tan solo deberemos de cambiar el nombre de las dos primeras líneas y escribir el nombre de las capas que hemos añadido. Estos scripts no sirven solo para estas dos capas, puedes reutilizarlo en tus proyectos.


from gvsig import *
from geom import *

def main(*args):
    """Selección de capas que intersectan"""

    #Capa con una linea
    lyrTrack = currentView().getLayer("line_10.shp")
    #Capa de poligonos
    lyrMunicipio = currentView().getLayer("MUNICIPIO.SHP")

    #Acceso a las entidades
    featuresTrack = lyrTrack.features()
    featuresMunicipio = lyrMunicipio.features()

    #Accede a la primera entidad (linea) de la capa line
    track1 = iter(featuresTrack).next()

    #Iteramos para ver por cuales municipios intersecta la linea
    for municipio in featuresMunicipio:
        if municipio.geometry().intersects(track1.geometry()):
            #Hace la seleccion si las geometrias interseccionan
            #municipio con el track
            lyrMunicipio.select(municipio)

    #Muestra todos los municipios seleccionados
    #si utilizas otra capa tuya, estos nombres corresponden
    #a los atributos que quieras mostrar
    for select in lyrMunicipio.getSelection():
        print select.MUNI_, select.NOMBRE

Y con esto, nos generaría una selección de los municipios por donde pasa el track. Por ejemplo, una pequeña variante es hacer una selección del área de influencia del track. Para ello la única diferencia que deberíamos aplicar es hacer el calculo en vez de sobre la geometría de la línea “track1.geometry()”, sobre el de su área de influencia de esa geometría “track1.geometry().buffer(10000)” con la distancia que deseemos.

Este cambio habría que aplicarlo a la línea: “if municipio.geometry().intersects(track1.geometry().buffer(10000)):”

webinar-scripting4

buffer = 0

webinar-scripting5

buffer = 10000

Ya está, con esta selección podríamos ejecutar otros scripts o trabajar con ella. Cualquier duda me la podéis comentar en el post o por email, espero que os sirva para animaros a probar este módulo de programación y si queréis aprender más os podéis apuntar al curso que damos sobre esto “Scripting en gvSIG2” en la plataforma de gvsig-training.

currentProjectEl próximo día 2 de Abril a las 14:00 UTC voy a dar una webinar online y gratuito sobre “Scripting en gvSIG” a través de la plataforma de MundoGEO. Realizare una pequeña introducción al Scripting, y realizaré un par de ejemplos de uso en el momento. Cualquiera está invitado y puede asistir desde su ordenador, podréis hacer preguntas o sino contactar conmigo luego que no hay ningún problema.

También anunciaremos el Curso de Scripting en gvSIG 2: Tratamiento de datos vectoriales que vamos a dar en la plataforma de gvsig-training para los que os decidáis a aprender más incluso si no sabéis programar empezaremos desde lo más básico.

Si quieres conocer más, asiste e infórmate:

qgis03

Llevaba ya tiempo queriendo publicar contenido sobre programación en otras plataformas, así que uno de los propósitos del año nuevo es empezar a publicar algún que otro post sobre programación en QGIS, que estoy seguro que alguno lo utilizareis y viene pegando fuerte desde su última versión. Eso sí, aún no tengo ni idea, así que publicaré según vaya aprendiendo cosas nuevas.

Y como todo lo que se empieza, lo primero que se hace es buscar información por Internet, así que lo primero que he encontrado es la documentación que dispone la web oficial de QGIS sobre el tema de programación, en principio utilizaré la última versión de QGIS 2.0 Dufour, y aparece el manual de usuario de QGIS y la guía del desarrollador de PyQGIS:

Creo que para empezar será suficiente con la documentación oficial, si alguno conoce mejor material soy todo oídos y acepto todo tipo de recomendaciones.Próximo post, primeros pasos para ejecutar nuestro primer script en PyQGIS.