Mesclar recursos espacialmente coincidentes na mesma classe de recursos

8

Eu preciso de uma maneira de mesclar programaticamente células de grade (polígono 15x15m) que estão diretamente umas sobre as outras e adicionar alguns de seus atributos.

Estou trabalhando no ArcGIS 10.1 com os dados armazenados como uma classe de recurso de polígono.

Os dados são o resultado da pesquisa de pedestres em uma grade predefinida. Ocasionalmente, as pessoas que conduzem a pesquisa com pedestres saem do curso e gravam algo em uma coluna ou linha adjacente àquela em que estão trabalhando (ou a posição do GPS vagueia). Isso resulta em dois conjuntos de dados sendo gravados para cada célula quando os dados de várias unidades GPS são anexados em uma única classe de recurso. Eu preciso de uma maneira de percorrer cada célula, verificar se há algum recurso duplicado, se há, então, mesclar seus atributos (algum número inteiro, algum texto) e excluir o único recurso que não obteve os dados mesclados.

As ferramentas 'Excluir idêntico' e 'Localizar idêntico' não fazem o que estou procurando - e fazê-lo manualmente não é uma opção, pois a classe de recurso geralmente possui mais de 10.000 recursos.

Eu sei como percorrer a classe de recurso usando python e verificar se existem recursos duplicados nesse local. O que não sei fazer é lidar com a mesclagem dos recursos e a atualização dos atributos. Se alguém puder oferecer alguma orientação sobre como fazer isso, eu agradeceria muito.

EDIT - Mais descrição do estado antes / depois: Na imagem abaixo, há dois recursos selecionados - polígonos idênticos de 15x15 metros quadrados, preciso adicionar todos os campos inteiros (aqueles com TOT_ como prefixo) e anexar o GPS_UNIT, INITIALS e REC_DATE.

É difícil mostrar, pois os recursos se sobrepõem diretamente.

insira a descrição da imagem aqui

EDIT 2: Descobri que posso identificar facilmente os recursos duplicados calculando seus centros XY, concatenando-os em um campo de string como [X] e ',' e [Y] e abrindo o banco de dados no acesso e usando uma consulta Localizar Duplicatas para identificar quais células foram duplicadas. No entanto, não consegui descobrir uma boa maneira de mesclar os atributos de cada célula em uma única linha. Ajuda com como fazer isso, seja em python ou em um ambiente de banco de dados, seria muito bem-vinda!

Kevin
fonte
1
Você pode postar uma pequena área de amostra com os estados "antes e depois da correção"?
blah238

Respostas:

2

Como você sabe como iterar e encontrar os recursos que deseja mesclar, eu criaria uma função para fazer a mesclagem que provavelmente poderia ser arcpy.Dissovle_management (). Faça a dissolução e você provavelmente poderá usar os parâmetros de agregação para combinar os atributos, excluir esses recursos do original e atualizar os dados novamente com um cursor de inserção.

Como você identifica quais recursos precisam ser mesclados?

Justin
fonte
Até agora, a melhor maneira de mesclar os recursos de ID é percorrer e fazer uma seleção por local, usando o recurso selecionado como origem e a camada como destino. Então, uso o arcpy.getCount para ver quantos recursos estão selecionados, se for mais de um, e preciso mesclar os atributos de todos os recursos selecionados em um e excluir os outros.
9113 Kevin
2

Acabei resolvendo esse problema depois de migrar para o Postgres e ter algumas ferramentas mais poderosas em mãos. Minha solução foi simplesmente excluir recursos extras com campos GEOM idênticos - deixando um, é claro, e depois recalcular os valores dos outros dados coletados durante o trabalho de campo. Isso me deu um conjunto de dados sem recursos coincidentes espacialmente e totais precisos nas tabelas de atributos. O código PHP completo que eu usei está abaixo; Estou certo de que o mesmo poderia ser realizado em Python, mas o PHP era a rota mais fácil para mim na época.

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>TRU Recalculation</title>
</head>

<body>
    <!-- Progress bar holder -->
    <div id="progress" style="width:500px;border:1px solid #ccc;"></div>
    <!-- Progress information -->
    <div id="information" style="width"></div>

    <?php
        $tot_deb = 0;
        $mfr_tool = 0;
        $tot_ltool = 0;
        $tot_gs = 0;
        $tot_cerl = 0;
        $tot_cern = 0;
        $tot_fcr = 0;
        $tot_pfeat = 0;
        $tot_hist = 0;
        $tot_hfeat = 0;
        $tot_art = 0;

        $dbconn = pg_connect("host=localhost port=54321 dbname=sixksurvey user=postgres password=password");

        $TRU_set = pg_query($dbconn, "select gid, east, north, tot_deb, mfr_tool, tot_ltool, tot_gs, tot_cerl, tot_cern, tot_fcr, tot_pfeat, tot_hist, tot_hfeat, comment, tot_art, surf_sed, visibility, hdop, sats, gps_unit, initials, rec_date from trutest_full order by north asc");

        $total = pg_num_rows($TRU_set);
        $i = 1; //Just a counter for the progress bar

        if (pg_num_rows($TRU_set) > 0)
        {
            while($current_TRU = pg_fetch_row($TRU_set))
            {

                if ($current_TRU) 
                {
                    // Calculate the percent
                    $percent = intval($i/$total * 100)."%";

                    // Javascript for updating the progress bar and information
                    echo '<script language="javascript">
                    document.getElementById("progress").innerHTML="<div style=\"width:'.$percent.';background-color:#2CA25F;\">&nbsp;</div>";
                    document.getElementById("information").innerHTML="'.$i.' TRU Cells Recalculated.";
                    </script>';

                    // Select all the LITHICS within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_Lithics = pg_query($dbconn,"SELECT type, art_count FROM lithic join trutest_full ON ST_CONTAINS(trutest_full.geom, lithic.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_LITHIC = pg_fetch_row($ALL_Lithics))
                    {
                        //If statement for tot_deb
                        if ($current_LITHIC[0] == 'Angular Debris' or $current_LITHIC[0] == 'Biface Thinning Flake' or $current_LITHIC[0] == 'Hammer stone')
                        {
                            $tot_deb += $current_LITHIC[1];
                        }

                        //If statement for mfr_tool
                        if ($current_LITHIC[0] == 'Test Nod/Core' or $current_LITHIC[0] == 'Reduced Core' or $current_LITHIC[0] == 'Core Red. Flake')
                        {
                            $mfr_tool += $current_LITHIC[1];
                        }
                        //If statement for tot_ltool
                        if ($current_LITHIC[0] == 'Scraper' or $current_LITHIC[0] == 'Uniface' or $current_LITHIC[0] == 'Retouched Tool' or
                            $current_LITHIC[0] == 'Proj. Point' or $current_LITHIC[0] == 'Biface' or $current_LITHIC == 'Other')
                        {
                            $tot_ltool += $current_LITHIC[1];
                        }
                    }


                    // Select all the CERAMICS within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_Ceramics = pg_query($dbconn,"SELECT type, art_count FROM ceramic JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, ceramic.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_CERAMIC = pg_fetch_row($ALL_Ceramics))
                    {
                        // Calculate new total for Local Ceramics
                        if ($current_CERAMIC[0] == 'EP Brown' or $current_CERAMIC[0] == 'EP brownware' or $current_CERAMIC[0] == 'EP Poly' or $current_CERAMIC[0] == 'EP Decorated' or $current_CERAMIC[0] == 'EP UB' or $current_CERAMIC[0] == 'Jornada Brown' or $current_CERAMIC[0] == 'EP Bichrome')
                        {
                            $tot_cerl += $current_CERAMIC[1];
                        }

                        // Calculate new total for Non-Local Ceramics
                        else
                        {
                            $tot_cern += $current_CERAMIC[1];
                        }
                    }
                    // Select all the FCR within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_fcr = pg_query($dbconn,"SELECT art_count FROM fcr JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, fcr.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_FCR = pg_fetch_row($ALL_fcr))
                    {
                        $tot_fcr += $current_FCR[0];
                    }               

                    // Select all the FEATURES within the current TRU and count them up 
                    $ALL_features = pg_query($dbconn,"SELECT type FROM fcr JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, fcr.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_Feat = pg_fetch_row($ALL_features))
                    {
                        // Test the type of the feature to identify the historic features (I started here because there are fewer types, this is faster).  Rather than try to count the rows,
                        // I just add 1 to each total for each feature that is being tested
                        if ($current_Feat[0] == 'Historic Artifact Conc.' or $current_Feat[0] == 'Historic Water Feature' or $current_Feat[0] == 'Historic Structure')
                        {
                            $tot_hfeat += 1;    
                        }
                        else
                        {
                            $tot_pfeat += 1;
                        }
                    }
                    // Select all the GS within the current TRU and count them up 
                    $ALL_gs = pg_query($dbconn,"SELECT art_count FROM gs JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, gs.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_GS = pg_fetch_row($ALL_gs))
                    {
                        $tot_gs += $current_GS[0];
                    }   

                    // Select all the HISTORIC within the current TRU and count them up according to their types, then assign the new count to the relevant total variable.
                    $ALL_historic = pg_query($dbconn,"SELECT art_count FROM historic JOIN trutest_full ON ST_CONTAINS(trutest_full.geom, historic.geom) WHERE trutest_full.gid = " . $current_TRU[0]);
                    while($current_HISTORIC = pg_fetch_row($ALL_historic))
                    {
                        $tot_hist += $current_HISTORIC[0];
                    }   

                    // Count all the artifacts and assign to TOT_ART
                    $tot_art = $tot_deb + $mfr_tool + $tot_ltool + $tot_cerl + $tot_cern + $tot_fcr + $tot_hist + $tot_gs;

                    // Something here to merge initials/date recorded/surface/visibiilty/etc into the comments for merged cells
                    // This code isn't the place to do this...  //Not dealing with duplicates here, just every cell in the set...


                    // Send the updated counts back to the database.
                    $result = pg_query($dbconn,"UPDATE trutest_full SET tot_deb = " . $tot_deb . ", mfr_tool = " . $mfr_tool . ", tot_ltool = " . $tot_ltool . ", tot_gs = " . $tot_gs . ", tot_cerl = " . $tot_cerl . ", tot_cern = " . $tot_cern . ", tot_fcr = " . $tot_fcr . ", tot_pfeat = " . $tot_pfeat . ", tot_hist = " . $tot_hist . ", tot_hfeat = " . $tot_hfeat . ", tot_art = " . $tot_art . " WHERE trutest_full.gid = " . $current_TRU[0]);

                    // This is for the buffer achieve the minimum size in order to flush data
                    echo str_repeat(' ',1024*64);

                    // Send output to browser immediately
                    flush();

                    if (!$result)
                    {
                        echo 'Update Query Failed in TRU.gid = ' . $current_TRU[0];
                    }

                    // Zero out all the hoppers for the next go-round
                    $tot_deb = 0;
                    $mfr_tool = 0;
                    $tot_ltool = 0;
                    $tot_gs = 0;
                    $tot_cerl = 0;
                    $tot_cern = 0;
                    $tot_fcr = 0;
                    $tot_pfeat = 0;
                    $tot_hist = 0;
                    $tot_hfeat = 0;
                    $tot_art = 0;

                    $i += 1;
                }
            }
        }
        echo 'TRU Recalculate Done';
    ?>

</body>
</html>
Kevin
fonte
0

Como você deseja mesclar atributos para células (na verdade polígonos) idênticos, eu usaria Union e manteria todos os atributos. Dessa forma, você pode percorrer todos os polígonos (células) resultantes e ter acesso aos dois conjuntos de atributos originais para escrever quaisquer novos valores que desejar. Se os mesmos nomes de atributo forem usados ​​pelas duas classes de recursos originais, talvez seja necessário renomear os campos antes da União para que ambos permaneçam disponíveis.

Na verdade, uma rápida releitura de sua pergunta me diz que você tem apenas uma classe de recurso de entrada. A união ainda pode ser útil porque pode ser executada em uma única classe de recurso, conforme descrito aqui .

PolyGeo
fonte
Eu não tinha pensado em usar Union em vez de Anexar ao combinar os dados de cada unidade GPS ... Isso eliminaria o problema de sobreposição espacial e, então, eu teria que lidar com o mais fácil. O que você pensa sobre questões que podem surgir ao unir mais de 20 aulas de cada vez?
9133 Kevin
Só que você provavelmente precisará ter o licenciamento Advanced (ArcInfo) se quiser fazê-lo de uma só vez. Com Básico e Padrão, você precisaria fazer Uniões em pares e agregar os resultados.
PolyGeo