Tutorial para convertir datos geoespaciales (ESRI shapefiles) a formatos 3D (VTK) con Python

ConvertgeospatialdataShapefileto3DdataVTKwithPythonGeopandasandPyvista.png

En nuestra perspectiva, la visualización 3D de datos geoespaciales ha sido una característica deseada desde hace mucho tiempo en SIG y que se ha cubierto en algunas características de SAGA GIS o en algunos complementos de QGIS. Esta vez desarrollamos un script en Python que convierte punto / línea / polígono de shapefiles ESRI (o cualquier archivo vectorial) al formato Vtk de grilla no estructurada (Vtu) mediante el uso de las bibliotecas de Python: Geopandas y Pyvista. El tutorial tiene archivos, scripts y videos que muestran todo el procedimiento con algunos comentarios sobre el software y los archivos espaciales y una discusión sobre la naturaleza de los archivos espaciales que presenta algunos desafíos en la conversión de datos.

Notas para este tutorial:

  • Todas las geometrías 3D están relacionadas con el atributo "Elev" y el campo de geometría del dataframe de Geopandas.

  • Los shapefiles de líneas deben ser partes individuales.

  • Los polígonos no deben tener agujeros o no se considerarán.

  • Los polígonos se exportan como líneas y no como polígonos debido al hecho de que los Vtks se diseñaron para polígonos convexos que tienen un rendimiento deficiente con polígonos geoespaciales.

Como usuarios habituales de formatos de datos Shapefile y Vtk, sabemos que el potencial de conversión es enorme; sin embargo, consideramos que este tutorial es un buen punto de partida para futuras mejoras o la aplicación en casos particulares.

Conozca más del formato VTK en este enlace:

https://lorensen.github.io/VTKExamples/site/VTKFileFormats/


Tutorial


Código

Este es el código en Python relacionado a la conversion:

#import required packages
import itertools
import numpy as np
import pyvista as pv
import geopandas as gpd
#for windows users
from shapely import speedups
speedups.disable()
C:\Users\GIDA2\miniconda3\lib\site-packages\geopandas\_compat.py:84: UserWarning: The Shapely GEOS version (3.4.3-CAPI-1.8.3 r4285) is incompatible with the GEOS version PyGEOS was compiled with (3.8.1-CAPI-1.13.3). Conversions between both will be slow.
  warnings.warn(
#create geodataframes from all shapefiles
pointDf = gpd.read_file('../Shps/wellPoints.shp')
lineDf = gpd.read_file('../Shps/contoursLines.shp')
polyDf = gpd.read_file('../Shps/lakesPolygons.shp')

For point type geometry

#create emtpy lists to collect point information
cellSec = []
cellTypeSec = []
pointSec = []

#iterate over the points
i = 0
for index, valuesx in pointDf.iterrows():
    x, y, z = pointDf.loc[index].geometry.x, pointDf.loc[index].geometry.y, pointDf.loc[index].Elev
    pointSec.append([x,y,z])
    cellTypeSec.append([1])
    cellSec.append([1,i])
    i+=1

#convert list to numpy arrays
cellArray = np.array(cellSec)
cellTypeArray = np.array(cellTypeSec)
pointArray = np.array(pointSec)

#create the unstructured grid object
pointUgrid = pv.UnstructuredGrid(cellArray,cellTypeArray,pointArray)

#we can add some values to the point
pointUgrid.cell_arrays["Elev"] = pointDf.Elev.values

#plot and save as vtk
pointUgrid.plot()
pointUgrid.save('../Vtks/wellPoint.vtu',binary=False)
output_3_0.png

For line type geometry

#create emtpy dict to store the partial unstructure grids
lineTubes = {}

#iterate over the points
for index, values in lineDf.iterrows():
    cellSec = []
    linePointSec = []

    #iterate over the geometry coords
    zipObject = zip(values.geometry.xy[0],values.geometry.xy[1],itertools.repeat(values.Elev))
    for linePoint in zipObject:
        linePointSec.append([linePoint[0],linePoint[1],linePoint[2]])

    #get the number of vertex from the line and create the cell sequence
    nPoints = len(list(lineDf.loc[index].geometry.coords))
    cellSec = [nPoints] + [i for i in range(nPoints)]

    #convert list to numpy arrays
    cellSecArray = np.array(cellSec)
    cellTypeArray = np.array([4])
    linePointArray = np.array(linePointSec)

    partialLineUgrid = pv.UnstructuredGrid(cellSecArray,cellTypeArray,linePointArray)   
    #we can add some values to the point
    partialLineUgrid.cell_arrays["Elev"] = values.Elev
    lineTubes[str(index)] = partialLineUgrid

#merge all tubes and export resulting vtk
lineBlocks = pv.MultiBlock(lineTubes)
lineGrid = lineBlocks.combine()
lineGrid.save('../Vtks/contourLine.vtk',binary=False)
lineGrid.plot()
output_5_0.png

For poly type geometry

#create emtpy dict to store the partial unstructure grids
polyTubes = {}

#iterate over the points
for index, values in polyDf.iterrows():
    cellSec = []
    linePointSec = []

    #iterate over the geometry coords
    zipObject = zip(values.geometry.exterior.xy[0],
                    values.geometry.exterior.xy[1],
                    itertools.repeat(values.Elev))
    for linePoint in zipObject:
        linePointSec.append([linePoint[0],linePoint[1],linePoint[2]])

    #get the number of vertex from the line and create the cell sequence
    nPoints = len(list(polyDf.loc[index].geometry.exterior.coords))
    cellSec = [nPoints] + [i for i in range(nPoints)]

    #convert list to numpy arrays
    cellSecArray = np.array(cellSec)
    cellTypeArray = np.array([4])
    linePointArray = np.array(linePointSec)

    partialPolyUgrid = pv.UnstructuredGrid(cellSecArray,cellTypeArray,linePointArray)   
    #we can add some values to the point
    partialPolyUgrid.cell_arrays["Elev"] = values.Elev
    #    partialPolyUgrid.save('../vtk/partiallakePoly.vtk',binary=False)
    polyTubes[str(index)] = partialPolyUgrid

#merge all tubes and export resulting vtk
polyBlocks = pv.MultiBlock(polyTubes)
polyGrid = polyBlocks.combine()
polyGrid.save('../Vtks/lakePolyasLines.vtk',binary=False)
polyGrid.plot()
output_7_0.png

Datos de entrada

Puede descargar los datos de entrada de este enlace.

 

Suscríbete a nuestro boletín electrónico

Suscríbase a nuestro boletín gratuito para recibir noticias, datos interesantes y fechas de nuestros cursos en recursos hídricos.

 

Posted on February 22, 2021 and filed under TutorialQGIS, TutorialPython.