Usando o ArcPy para obter simbologia de camadas?

16

Como o ArcGIS 10 vem com o pacote ArcPy, eu estou imaginando que é possível usar as funções do ArcPy para obter a simbologia (ou seja, cor, largura ...) de uma camada?

VietThanh Le
fonte

Respostas:

15

Para o ArcGIS 10.0, se você pode usar uma abordagem somente leitura, a seguinte amostra de código revela o campo (e a tabela unida) que formam a base para a simbologia de uma camada. Ele exporta um msd temporário (um zip contendo arquivos xml) e carrega os atributos específicos em um objeto. Essas classes podem ser estendidas para obter acesso a atributos adicionais da camada.

import zipfile
from arcpy import mapping
import os
from xml.dom.minidom import parse


class LayerExtras(object):
    """ An object to hold attributes loaded from xml inside the msd."""

    name = ""
    symbologyFieldName = ""


class MxdExtras(dict):
    """ Exposes extra MXD details by raiding an exported msd

        Treat this object as a dictionary with layer name as the key and a custom object
        with desired attributes as the value.
        You must have write access to MXD directory (creates temporary msd file).
        Only layers in the first dataframe are accessed.

    """    

    LYR_NAME_NODE = "Name"
    LYR_SYMBOL_NODE = "Symbolizer"
    LYR_FIELD_NODE = "Field"
    MSD_SUFFIX = "_MxdExtrasTemp.msd"
    MXD_SUFFIX = ".mxd"
    EXCLUDED_FILE_NAMES = ["DocumentInfo.xml", "layers/layers.xml"]
    mxdPath = ""

    def __init__(self, mxdPath):

        self.loadMxdPath(mxdPath)


    def loadMxdPath(self, mxdPath):
        """ Load mxd from file path """

        self.mxdPath = mxdPath.lower()
        mxd = mapping.MapDocument(self.mxdPath)

        msdPath = self.mxdPath.replace(self.MXD_SUFFIX, self.MSD_SUFFIX) 

        # Delete temporary msd if it exists
        if os.path.exists(msdPath):
            os.remove(msdPath)

        mapping.ConvertToMSD(mxd,msdPath)

        zz = zipfile.ZipFile(msdPath)

        for fileName in (fileName for fileName in zz.namelist() if not fileName in self.EXCLUDED_FILE_NAMES):
            dom = parse(zz.open(fileName))
            name, lyr = self.loadMsdLayerDom(dom)
            self[name] = lyr
        del zz
        os.remove(msdPath)

    def loadMsdLayerDom(self, dom):
        """ Load dom created from xml file inside the msd. """

        lyr = LayerExtras()  

        # Layer name
        lyr.name = dom.getElementsByTagName(self.LYR_NAME_NODE)[0].childNodes[0].nodeValue

        # Symbology field name
        symbologyElement = dom.getElementsByTagName(self.LYR_SYMBOL_NODE)[0]
        lyr.symbologyFieldName = symbologyElement.getElementsByTagName(self.LYR_FIELD_NODE)[0].childNodes[0].nodeValue

        return lyr.name, lyr


############
# Test

if __name__ == "__main__":

    mxdPath = r"c:\temp\AmphibianSpeciesRichnessAverageOf30mCells.mxd"

    mxde = MxdExtras(mxdPath)

    for lyr in mxde.itervalues():
        print "Layer Name: ", lyr.name 
        print "Layer Symbology Field Name: ", lyr.symbologyFieldName
        print 

Exemplo de saída do teste:

Layer Name:  Amphibian Species Richness Average of 30m Cells
Layer Symbology Field Name:  biodiversity.AmphAve
MJ
fonte
Use um gerenciador de contexto para esse arquivo zip: with zipfile.ZipFile(msdPath) as zz:.
jpmc26
@ MichaelJackson No seu código, substituí apenas o caminho do mxd. Mas recebi um erro na linha `lyr.symbologyFieldName = symbologyElement.getElementsByTagName (self.LYR_FIELD_NODE) ​​[0] .childNodes [0] .nodeValue`, dizendo list index out of range. isso ocorre porque o symbologyElement.getElementsByTagName(self.LYR_FIELD_NODE)está vazio. Mas por que está vazio? Eu assumi que essa é uma alternativa ao método lyr.symbology, mas ainda não funciona.
Panda
@ panda Esta é uma resposta antiga. Você está usando a versão superior à 10.0? Se sim, consulte a resposta abaixo sobre a propriedade simbologia do objeto de camada.
MJ
@ MichaelJackson Eu uso a propriedade simbologia, mas parece que não é suportada em todos os casos, como quando a camada usa mais de um campo para simbologia. Preciso obter os nomes dos campos usados, mas não consigo encontrar um método.
Panda
10

O ArcPy procura permitir que você altere a simbologia, mas apenas com os arquivos .lyr existentes , e não especifique os símbolos diretamente no seu código, com base na minha leitura do módulo.

scw
fonte
6

No ArcGIS 10.1 e mais recente, há acesso direto à simbologia através da propriedade simbologia do objeto de camada .

Para o ArcGIS 10.0, as soluções alternativas mencionadas funcionaram para mim.

Bernd
fonte
infelizmente, a simbologia de uma camada é somente leitura (de acordo com a quinta instância de "simbologia" nesta página , bem como a que você citou).
Roland
1
No entanto, "nem todos os tipos de classe de simbologia de camada são suportados; para aqueles que não são, a palavra-chave OTHER é retornada." . Os tipos não suportados incluem valores exclusivos de varredura, valores exclusivos de muitos campos e densidade de pontos. Isso ainda é verdade no ArcGIS 10.5. Se você é o suficiente sorte de ter um SymbologyType suportados ver roteiro no gis.stackexchange.com/questions/184133/...
Matt Wilkie