3 votos

Python, OGR y Mapnik: ¿Es posible pasar un origen de datos existente de `ogr.Open()` a Mapnik sin usar `mapnik.Ogr()`?

Estoy tratando de modificar create_utfgrids.py para usar un archivo VRT de OGR, en lugar de shapefiles, y aunque el código relacionado con OGR en este código responde al VRT, el código de Mapnik no. Está fallando con..

ERROR 1: Error al abrir la fuente de datos `PG:host=127.0.0.1 user=postgres dbname=gis password=passw0rd tables=parcels_20140829_pmerc'.

Creo que el VRT está bien, porque no solo funciona con ogrinfo directamente, sino que como se mencionó anteriormente, el código relacionado con OGR en el archivo Python también funciona.

Aunque estoy bastante seguro de que el problema no es el VRT, para aquellos que puedan preguntar, el VRT que probé se ve así. Sé que hay cosas redundantes allí, pero pensé que tal vez Mapnik estaba buscando algo específico, así que estaba agregando cualquier nodo que pudiera ser relevante:

    PG:host=127.0.0.1 user=postgres dbname=gis password=passw0rd tables=parcels_20140829_pmerc
    parcels_20140829_pmerc
    EPSG:3857
    SELECT ST_AsBinary(wkb_geometry) as geomm, tms, owner_name, the_wkt FROM parcels_20140829_pmerc

Eventualmente logré resolver el problema pasando una cadena de conexión de PostgreSQL de OGR, analizando eso y luego insertando los valores en un constructor mapnik.PostGIS(). Seguro, esto resuelve mi problema inmediato, pero no es tan genérico/universal como me gustaría.

Entonces me pregunto, dado que no puedo hacer que Mapnik acepte mi VRT, si es posible hacer referencia al objeto de fuente de datos existente de ogr.Open() desde Mapnik y evitar tener que usar algo como mapnik.PostGIS() o mapnik.Ogr() en primer lugar.

Para obtener esta idea, así es como me lo imagino..

import mapnik
import ogr

# create_utfgrids.py usa shapefiles, por lo tanto "shppath".
# Pero para este ejercicio representa una ruta a un VRT.
ds = ogr.Open(shppath)

# Aquí va un montón de cosas de OGR.

# Aquí es donde quiero que ocurra la magia,
# insertando el conjunto de datos de OGR en Mapnik..
ds = mapnik.Ogr(ds)

# Y luego sigue lo de Mapnik.

4voto

ESV Puntos 4591

Dependiendo de tu versión de mapnik, sí es posible. Mapnik 2.1 introdujo el Plugin de Python como una fuente de datos.

Necesitarías heredar de mapnik.PythonDatasource e implementar un método features que, basado en un objeto mapnik.Query entrante, devolverá objetos mapnik.PythonDatasource.wkb_features.

Por ejemplo:

import mapnik
import ogr

class VRTDataSource(mapnik.PythonDatasource):

    def __init__(self, shppath, layer_idx=0):
        self.ds = ogr.Open(shppath)
        self.layer_idx = layer_idx
        super(VRTDatasource, self).__init__()

    def features(self, query):
        bounding_box = query.bbox

        layer = self.ds[self.layer_idx]

        layer.SetSpatialFilterRect(
            bounding_box.minx,
            bounding_box.miny,
            bounding_box.maxx,
            bounding_box.maxy
        )

        return mapnik.PythonDatasource.wkb_features(
            keys = layer[0].keys(),  # Suponiendo que todas las características tienen la misma definición de tabla
            features = [
                ( feature.GetGeometryRef().ExportToWkb(), dict(feature) ), 
                for feature in layer # Las capas de OGR son iteradores de características
            ]
        )

# Luego cuando estás construyendo tu objeto de mapa mapnik

ds = mapnik.Python(factory='VRTDataSource', shppath=ruta, layer_idx=0)
layer = mapnik.Layer('python')
layer.datasource = ds

El único punto en el que me preocuparía sería la Proyección - No estoy seguro si mapnik pasará el CRS como parte del objeto mapnik.Query y esperará un WKB proyectado a cambio, o si establecer la proyección de la capa mapnik significa que mapnik proyectará sobre la marcha. Mi suposición sería la primera opción, pero me gustaría probar primero.

ACTUALIZACIÓN Expande el código de ejemplo para que no necesites especificar nada más allá de la fuente de datos y el nombre de la capa (asumiendo que el esquema de la capa es consistente).

3voto

pepoluan Puntos 3010

Volviendo atrás, si tienes datos en PostGIS y quieres representarlos con Mapnik, realmente deberías estar utilizando el soporte nativo de PostGIS de Mapnik - también conocido como mapnik.PostGIS conexión de datos en python (https://github.com/mapnik/mapnik/wiki/PostGIS). Eso será más rápido y eficiente que pasar por OGR. Dicho esto, si tienes una buena razón para conectar a PostGIS a través de un archivo OGR VRT, entonces eso debería funcionar bien a través de la conexión de datos de Mapnik mapnik.Ogr(). Recomendaría hacer que eso funcione (por favor, abre un problema en https://github.com/mapnik/mapnik-support con detalles sobre cómo replicarlo) en lugar de utilizar el complemento de python porque el complemento de python será la opción más lenta de todas.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X