Hợp nhất các tính năng trùng khớp không gian trong cùng một lớp tính năng


8

Tôi cần một cách để hợp nhất các ô lưới theo cách lập trình (đa giác 15x15m) trực tiếp lên nhau và thêm một số thuộc tính của chúng.

Tôi đang làm việc trong ArcGIS 10.1 với dữ liệu được lưu trữ dưới dạng lớp tính năng đa giác.

Dữ liệu là kết quả của cuộc khảo sát người đi bộ trên một lưới được xác định trước. Thỉnh thoảng, những người thực hiện khảo sát người đi bộ ra khỏi khóa học và ghi lại một cái gì đó trong một cột hoặc hàng liền kề với cái họ đang làm việc (hoặc những người lang thang vị trí GPS). Điều này dẫn đến hai bộ dữ liệu được ghi lại cho mỗi ô khi dữ liệu từ nhiều đơn vị GPS được thêm vào một lớp tính năng duy nhất. Tôi cần một cách để đi qua từng ô, kiểm tra xem liệu có bất kỳ tính năng trùng lặp nào không, nếu có sau đó hợp nhất các thuộc tính của chúng (một số nguyên, một số văn bản), sau đó xóa một tính năng không nhận được dữ liệu đã hợp nhất.

Các công cụ 'Xóa giống hệt' và 'Tìm giống hệt' không làm những gì tôi đang tìm kiếm - và thực hiện thủ công không phải là một tùy chọn vì lớp tính năng thường có tới 10.000 tính năng trong đó.

Tôi biết cách lặp qua lớp tính năng bằng python và kiểm tra để xác định xem có bất kỳ tính năng trùng lặp nào trong vị trí đó không. Những gì tôi không biết làm thế nào là đối phó với việc hợp nhất các tính năng và cập nhật các thuộc tính. Nếu bất cứ ai có thể đưa ra một số hướng về cách thực hiện điều này, tôi sẽ đánh giá rất cao nó.

EDIT - Mô tả thêm về trạng thái trước / sau: Trong hình bên dưới có hai tính năng được chọn - đa giác vuông 15x15 mét giống hệt nhau, tôi cần thêm tất cả các trường số nguyên (các trường có TOT_ làm tiền tố) và nối thêm GPS_UNIT, INITIALS và các trường chuỗi REC_DATE.

Thật khó để hiển thị vì các tính năng chồng chéo trực tiếp.

nhập mô tả hình ảnh ở đây

EDIT 2: Tôi đã thấy rằng tôi có thể dễ dàng xác định các tính năng trùng lặp bằng cách tính toán các trung tâm XY của chúng, nối chúng thành một trường chuỗi như [X] & ',' & [Y] sau đó mở cơ sở dữ liệu truy cập và sử dụng truy vấn Tìm trùng lặp để xác định các ô nào đã được nhân đôi. Tuy nhiên, tôi chưa thể tìm ra một cách hay để hợp nhất các thuộc tính cho mỗi ô thành một hàng. Trợ giúp về cách làm điều đó, trong python hoặc trong môi trường cơ sở dữ liệu, sẽ rất được hoan nghênh!


1
Bạn có thể đăng một khu vực mẫu nhỏ với trạng thái "trước và sau khi sửa" không?
blah238

Câu trả lời:


2

Vì bạn biết cách lặp và tìm các tính năng mà bạn muốn hợp nhất, tôi sẽ xây dựng một hàm để thực hiện hợp nhất có thể là arcpy.Dissovle_man Quản lý (). Thực hiện hòa tan và bạn có thể có thể sử dụng các tham số tổng hợp để kết hợp các thuộc tính sau đó xóa các tính năng đó khỏi bản gốc và cập nhật dữ liệu trở lại bằng một con trỏ chèn.

Làm thế nào để bạn xác định các tính năng cần phải được hợp nhất?


Cho đến nay, cách tốt nhất để hợp nhất các tính năng ID là lặp lại và thực hiện chọn theo vị trí bằng cách sử dụng tính năng được chọn làm nguồn và lớp làm mục tiêu. Sau đó, tôi sử dụng arcpy.getCount để xem có bao nhiêu tính năng được chọn, nếu đó là nhiều tính năng, thì tôi cần hợp nhất các thuộc tính của tất cả các tính năng được chọn thành một và xóa các tính năng khác.
Kevin

2

Cuối cùng tôi đã giải quyết vấn đề này sau khi tôi di chuyển đến Postgres và có sẵn một số công cụ mạnh hơn. Giải pháp của tôi là chỉ cần xóa các tính năng bổ sung với các trường GEOM giống hệt nhau - tất nhiên để lại một tính năng và sau đó tính toán lại các giá trị từ dữ liệu khác được thu thập trong quá trình điền dã. Điều này đã cho tôi một bộ dữ liệu không có tính năng trùng khớp không gian và tổng số chính xác trong các bảng thuộc tính. Mã PHP đầy đủ mà tôi đã sử dụng ở bên dưới; Tôi chắc chắn điều tương tự có thể được thực hiện trong Python nhưng PHP là con đường dễ nhất đối với tôi vào thời điểm đó.

    <!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>

0

Vì bạn chỉ muốn hợp nhất các thuộc tính cho tế bào (trên thực tế đa giác) mà là giống hệt nhau sau đó tôi sẽ sử dụng Liên minh và giữ tất cả các thuộc tính. Bằng cách đó, bạn có thể lặp qua tất cả các đa giác (ô) kết quả và có quyền truy cập vào cả hai bộ thuộc tính ban đầu để viết bất kỳ giá trị mới nào bạn muốn. Nếu cả hai tên thuộc tính giống nhau được sử dụng bởi cả hai lớp đối tượng gốc, bạn có thể cần thực hiện một số đổi tên của các trường trước Liên minh để cả hai vẫn có sẵn.

Trên thực tế, việc đọc lại nhanh câu hỏi của bạn cho tôi biết rằng bạn chỉ có một lớp tính năng đầu vào. Liên minh có thể vẫn hữu ích vì nó có thể chạy với một lớp đối tượng duy nhất như được mô tả ở đây .


Tôi đã không nghĩ sử dụng Union thay vì chắp thêm khi kết hợp dữ liệu từ mỗi đơn vị GPS ... Làm như vậy sẽ loại bỏ vấn đề chồng chéo không gian và sau đó tôi sẽ phải giải quyết dễ dàng hơn. Bạn có suy nghĩ gì về các vấn đề có thể phát sinh khi kết hợp 20 lớp tính năng cùng một lúc không?
Kevin

Chỉ có điều bạn có thể cần phải có giấy phép Nâng cao (ArcInfo) nếu bạn muốn làm điều đó trong một lần. Với Cơ bản và Tiêu chuẩn, bạn sẽ cần thực hiện các hiệp hội theo cặp và tổng hợp kết quả.
PolyGeo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.