ArcGIS Pro consente di customizzare la toolbox con script esterni scritti in linguaggio Python. Questo processo consente di espandere le funzionalità a piacere dell’utente, rendendolo particolarmente efficiente per operazioni che richiedono molti passaggi e/o schedulate nel tempo. A differenza di ArcGIS Desktop, la versione PRO utilizza la release di Python 3 e il modulo affidato a tutte le funzioni di ArcGIS è denominato arcpy.

Importare script esterni

Per importare script python bisogna prima creare una propria toolbox. Per fare questo è sufficiente accedere alla Ribbon Tab “Insert” e dalla Dialog Box “Project” selezionare Toolbox -> New Toolbox

In alternativa si può accedere al Panes “Catalog” e clickando con il tasto destro su Toolboxes si può creare una nuova toolbox oppure aggiungere quella appena creata.

Una volta creata la nostra toolbox potremo andare a popolarla con script esterni clickando con il tasto destro New -> Script. Dalla finestra che si apre dovremo solamente inserire il nome che vogliamo dare alla funzione e puntare al file dove è salvato lo script.
In questo articolo analizziamo la casistica più semplice ovvero dove non ci sono parametri esterni.

Lo Script

Lo script che andremo ad analizzare serve per ordinare la gerarchia dei layer cercando di minimizzare la possibilità che una feature più grande nasconda una più piccola. Seguendo questa logica andremo a posizionare prima le feature puntiformi, in seguito quelle lineari e per finire i poligoni. Qualora siano presenti più layer della stessa geometria verrà considerata la sua numerosità/lunghezza/area (in base alla geometria point/line/polygon) e ordinata a sua volta in modo crescente.

Le prime righe di uno script sono adibite all’importazione dei moduli che si andranno ad utilizzare. I moduli sono librerie di funzioni utili per non dover riscrivere spesso operazioni comuni.

from arcpy import *
# import arcpy
import pandas as pd

Consigli:
Con il comando “from nome_modulo import *” non sarà necessario richiamare il nome del modulo per ogni sua funzione, in caso di import di più moduli risulta invece più chiara la sintassi “import arcpy” per non avere ambiguità sull’appartenenza di una funzione al modulo.
Con il comando “import nome_modulo as sigla” non sarà necessario richiamare per intero il nome del modulo per ogni sua funzione ma sarà sufficiente mettere la sigla come prefisso.

A seguire vi sarà una sezione dedicata alla creazione di tutte le variabili utili all’interno dello script. Noi ci appoggeremo a un dataframe pandas (NON è un dataframe arcgis) per salvare i valori dei layer e calcolare l’ordine.

df = pd.DataFrame(columns=['layer','geom','size'])
p = mp.ArcGISProject('CURRENT')
m = p.listMaps()[0]

Ora sarà sufficiente scorrere tutti i layer presenti nel progetto, differenziarli in base alla loro geometria e salvare la loro dimensione nel dataframe.

try:
    for lyr in m.listLayers():
        if (Describe(lyr).shapeType == 'Point') or (Describe(lyr).shapeType == 'Multipoint'):
            dimensione = int(management.GetCount(lyr)[0])
            geometria = Describe(lyr).shapeType
            df_length = len(df)
            df.loc[df_length] = [lyr,geometria,dimensione]
        elif Describe(lyr).shapeType == 'Polyline':
            dimensione = da.SearchCursor(lyr,'Shape_Length')
            somma = 0
            float(somma)
            for row in dimensione:
                somma += row[0]
            geometria = Describe(lyr).shapeType
            df_length = len(df)
            df.loc[df_length] = [lyr,geometria,somma]
        elif Describe(lyr).shapeType == 'Polygon':
            dimensione = da.SearchCursor(lyr,'Shape_Area')
            somma = 0
            float(somma)
            for row in dimensione:
                somma += row[0]
            geometria = Describe(lyr).shapeType
            df_length = len(df)
            df.loc[df_length] = [lyr,geometria,somma]
        elif lyr.isBasemapLayer == True:
            pass
        elif lyr.isRasterLayer == True:
            pass
        else:
            pass			
except:
    pass

Attenzione:
Per le geomtrie lineari e poligonali la dimensione è data dalla sommatoria della lunghezza/area di tutti i record.

Nel passo successivo andremo a ordinare i layer nel dataframe inserendo come campo primario la geometria e come campo secondario la dimensione

df['geom']=pd.Categorical(df['geom'],['Point','Multipoint','Polyline','Polygon'])
df2 = df.sort_values(["geom","size"])
df2 = df2.reset_index(drop=True)

Per finire bisogna scorrere la lista dei layer ordinati dall’ultimo al primo e posizionarli in testa al progetto. Ad ogni ciclo viene aggiornata la lista dei layer in quanto ne viene modificato l’ordine.

for i in range(max(df.index),-1,-1):
	m.moveLayer(df.loc[0,'layer'],df2.loc[i,'layer'], 'BEFORE')
	#print('ref: ',df.loc[0,'layer'])
	#print('move: ',df2.loc[i,'layer'])
	del df
	m = p.listMaps()[0]
	df = pd.DataFrame(columns=['layer','geom'])
	try:
		for lyr in m.listLayers():
			geometria = Describe(lyr).shapeType
			df_length = len(df)
			df.loc[df_length] = [lyr,geometria]
	except:
		pass

 

Per chi volesse copiare tutto il codice:

from arcpy import *
import pandas as pd
df = pd.DataFrame(columns=['layer','geom','size'])

p = mp.ArcGISProject('CURRENT')
m = p.listMaps()[0]
try:
    for lyr in m.listLayers():
        if (Describe(lyr).shapeType == 'Point') or (Describe(lyr).shapeType == 'Multipoint'):
            dimensione = int(management.GetCount(lyr)[0])
            geometria = Describe(lyr).shapeType
            df_length = len(df)
            df.loc[df_length] = [lyr,geometria,dimensione]
        elif Describe(lyr).shapeType == 'Polyline':
            dimensione = da.SearchCursor(lyr,'Shape_Length')
            somma = 0
            float(somma)
            for row in dimensione:
                somma += row[0]
            geometria = Describe(lyr).shapeType
            df_length = len(df)
            df.loc[df_length] = [lyr,geometria,somma]
        elif Describe(lyr).shapeType == 'Polygon':
            dimensione = da.SearchCursor(lyr,'Shape_Area')
            somma = 0
            float(somma)
            for row in dimensione:
                somma += row[0]
            geometria = Describe(lyr).shapeType
            df_length = len(df)
            df.loc[df_length] = [lyr,geometria,somma]
        elif lyr.isBasemapLayer == True:
            pass
        elif lyr.isRasterLayer == True:
            pass
        else:
            pass
            #geometria = Describe(lyr).shapeType
            #df_length = len(df)
            #df.loc[df_length] = [lyr,,]			
except:
    pass
		
df['geom']=pd.Categorical(df['geom'],['Point','Multipoint','Polyline','Polygon'])
df2 = df.sort_values(["geom","size"])
df2 = df2.reset_index(drop=True)

for i in range(max(df.index),-1,-1):
	m.moveLayer(df.loc[0,'layer'],df2.loc[i,'layer'], 'BEFORE')
	del df
	m = p.listMaps()[0]
	df = pd.DataFrame(columns=['layer','geom'])
	try:
		for lyr in m.listLayers():
			geometria = Describe(lyr).shapeType
			df_length = len(df)
			df.loc[df_length] = [lyr,geometria]
	except:
		pass

Per maggiori informazioni contatta lo staff GIS One Team via mail a gis@oneteam.it o chiamaci al numero 0247719331.

Iscriviti al blog per non perdervi i prossimi appuntamenti della serie ArcGIS Pro episodi!

SketchUp - Iscriviti al blog!

Leave a Comment