Crear un libro de mapas en ArcGIS Pro con Python

983
0
09-30-2015 06:56 AM
Esri Esteemed Contributor
1 0 983

Uno de los ejemplos que se mostró durante la presentación de Python en ArcGIS Pro (CCU2015) fue la generación de un libro de mapas, haciendo uso del nuevo módulo arcpy.mp de ArcGIS Pro y la opción de usar múltiples layout. Para el ejemplo se utilizó un proyecto con los siguientes elementos:

  • Mapa "Antioquia", con el límite del departamento de Antioquia y sus subregiones
  • Mapa "Subregion", con la capa de subregiones (con query de definición) y una capa de municipios (con query de definición)
  • Layout "Portada", con un título del libro, el mapa Antioquia y una imagen.
  • Layout "Contenido", con el texto "Contenido" y otro elemento de texto con el nombre "txtContenido"
  • Layout "laySubRegion", con el título de la subregión el mapa "Subregion" y un texto para indicar la página.

El objetivo era hacer un bucle y correr a través de los subregiones y exportar un mapa por cada subregión. Además tenemos la portada y una hoja de contenido. El resultado final debe ser un libro combinando todas las hojas.

Para trabajar con el proyecto actual debe hacerse la conexión usando la palabra clave "CURRENT" para indicar el proyecto actualmente abierto.

# -*- coding: utf-8 -*- import os  # configuración del ambiente para sobrescribir los archivos PDF arcpy.env.overwriteOutput = True  # crear enlace a proyecto Pro actualmente abierto proy = arcpy.mp.ArcGISProject("CURRENT")

Para carpeta de salida, tenemos una carpeta "pdf" ya creada en la carpeta del proyecto. Para determinar la ruta a esta carpeta podemos usar la propiedad "filePath" del proyecto:

# carpeta PDF ws, pr = os.path.split(proy.filePath) carpeta_pdf = os.path.join(ws, "pdf")

Debemos generar el enlace a los objetos de layout en el proyecto. Para hacerlo hacemos uso del método "listLayouts" del proyecto, suministrando el nombre de cada layout:

# crear enlaces a layouts lyt_por = proy.listLayouts("Portada")[0] lyt_cont = proy.listLayouts("Contenido")[0] lyt_subr = proy.listLayouts("laySubRegion")[0]

Hay unos objetos de texto en los layout que queremos manipular (la tabla de contenido, el título del Subregión y el número de la página):

# crear enlace a la lista de contenido txt_cont = lyt_cont.listElements('TEXT_ELEMENT','txtContenido')[0] txt_pag = lyt_subr.listElements('TEXT_ELEMENT','txtPagina')[0] txt_subr = lyt_subr.listElements('TEXT_ELEMENT','txtSubRegion')[0]

Accedemos al mapframe con los municipios y subregiones y a las capas (municipios y subregiones) para las cuales queremos definir el query para mostrar solamente una subregión a la vez y los municipios correspondientes:

# mapframe y capas para definir el query mf = lyt_subr.listElements('MAPFRAME_ELEMENT', 'Subregion Map Frame')[0] lyr_muni = mf.map.listLayers("Municipios")[0] lyr_subr = mf.map.listLayers("SubRegiones")[0]

Para la definición de los consulta (queries) es necesario definir los campos:

# campos para usar en query fld_subr = "NOM_DIV_TERRITORIAL2" fld_code_subr = "COD_DIV_TERRITORIAL2" fld_code_muni = "COD_DIV_SUPERIOR"

El nombre de la subregión usamos para llenar el título de la hoja. El campo de código de nivel superior de los municipios corresponde al al código de subregiones y nos permite consultar los municipios por subregión:

Para hacer el bucle para correr a través de todos los subregiones, debemos acceder a la capa de subregiones del mapa Antioquia.

# abrir capa de Subregiones para listar subregiones md_ant = proy.listMaps("Antioquia")[0] fc_subreg = md_ant.listLayers("Subregiones")[0]

El proceso de generar el libro comience por exportar la portada tal cual como está:

# inicialmente exportar portada print("Exportando portada") pdf_libro = os.path.join(carpeta_pdf, "mi_libro.pdf") lyt_por.exportToPDF(pdf_libro)

Luego debemos iniciar el bucle sobre las subregiones. Antes de iniciarlo definimos el número de la página donde empiece la tabla de contenido, un listado vacío para el texto de la tabla de contenido y un listado vacío para registrar las rutas de los archivos PDF que generamos en el proceso:

page = 2 lst_content = [] lst_pdf = []

El bucle se hace sobre el featureclass con todas las subregiones y con los campos necesarios y iniciemos a leer los datos de cada subregión (nombre y código):

# iniciar el bucle with arcpy.da.SearchCursor(fc_subreg, ("SHAPE@", fld_subr, fld_code_subr)) as curs:     for row in curs:         # para cada subregion, leer datos         page += 1         ext = row[0].extent         nombre = row[1]         codigo = row[2]         print("Exportando subregion '{0}'".format(nombre))

Luego aplicamos algunos de los datos del subregión actual;al listado de contenido agregamos un elemento con el nombre de la subregión y la página correspondiente. Para la capa de subregiones y municipios aplicamos un query de definición. En el proceso hacemos uso de arcpy.AddFieldDelimiters que no genere el formato correcto de la consulta SQL:

        # ajustar listado de contenido y aplicar query definition         lst_content.append("{0} .......... {1}".format(nombre, page))         lyr_subr.definitionQuery = "{0} = '{1}'".format(arcpy.AddFieldDelimiters(lyr_subr, fld_subr), nombre)         lyr_muni.definitionQuery = "{0} = '{1}'".format(arcpy.AddFieldDelimiters(lyr_muni, fld_code_muni), codigo)

En ArcGIS Pro para ajustar el extent (rango X y Y) de los datos, se debe usar el nuevo objeto camera. Ya leímos el extent de la subregion y ahora podemos aplicarlo. Además aumentamos la escala con 5% para generar un poco de margen al rededor de la subregión:

        # ajustar extent del mapa         mf.camera.setExtent(ext)         mf.camera.scale = mf.camera.scale * 1.05

Luego ajustamos el título de la página (nombre subregión) y el número de la página. Definimos un nombre de salida para el pdf, lo adicionamos a nuestra listado con los archivos pdf y exportamos el layout:

        # ajustar textos en la pagina y exportar la hoja         txt_subr.text = nombre         txt_pag.text = "Pagina {0}".format(page)         pdf_subr =os.path.join(carpeta_pdf, "{0}.pdf".format(nombre))         lst_pdf.append(pdf_subr)         lyt_subr.exportToPDF(pdf_subr)

Este proceso se repite para todas las subregiones. Una vez que se termine exportar los archivos pdf para cada subregión, podemos generar la hoja para la tabla de contenido. Recuerde que tenemos un listado que para cada subregión tiene un elemento con el nombre de la subregión y su página correspondiente. Podemos hacer un join de este listado utilizando una cadena de texto "\n" (=Enter). Esto nos genera un texto con en cada renglon la información de una subregión. Luego exportamos el contenido a archivo PDF y insertamos la ruta del pdf en el comienzo (índice = 0) de nuestra listado con los archivos pdf.

# crear la pagina de contenido print("Exportando contenido") txt_cont.text = "\n".join(lst_content) pdf_cont = os.path.join(carpeta_pdf, "Contenido.pdf") lyt_cont.exportToPDF(pdf_cont) lst_pdf.insert(0, os.path.join(carpeta_pdf, "Contenido.pdf"))

Para generar un sola PDF, podemos agregar los elementos del listado de los archivos pdf a nuestro pdf de la portada con el siguiente código (simplemente haciendo un bucle y insertando cada hoja):

# agregar las hojas al libro print("Armando libro") pdf_doc = arcpy.mp.PDFDocumentOpen(pdf_libro) for pdf_hoja in lst_pdf:     pdf_doc.appendPages(pdf_hoja) pdf_doc.saveAndClose()

Al final eliminemos los variables que creamos en el proceso.

# eliminar variables del proy, lyt_por, lyt_cont, lyt_subr, lyr_muni, lyr_subr, txt_cont, txt_pag del txt_subr, mf, md_ant, fc_subreg, pdf_libro, ext, pdf_subr, pdf_cont del pdf_doc print("listo")

Y eso es todo...

About the Author
Solution Engineer for the Utilities Sector @ Esri Colombia - Ecuador - Panamá sr GIS Advisor / Python - Arcpy developer / GIS analyst / technical project leader / lecturer and GeoNet moderator, focusing on innovations in the field of GIS. Specialties: ArcGIS, Python, ArcGIS Enterprise, ArcGIS Online, Arcade, Configurable Apps, WAB, Mobile Apps, Insights, Spatial Analysis, LiDAR / 3D Laser Scanning / Point Clouds. UNME http://nl.linkedin.com/in/xanderbakker/ http://www.slideshare.net/XanderBakker http://www.scribd.com/xbakker http://twitter.com/#!/XanderBakker
Labels