چند ضلعی های همسایه را در یک لایه پیدا کنید

توجه

اگر از QGIS3 استفاده می کنید، راه ساده تر و بهتری برای انجام این تحلیل با استفاده از تابع جمع وجود دارد. پست من را ببینید «پیدا کردن چند ضلعی های همسایه با استفاده از تابع جمع خلاصه در QGIS <https://spatialthoughts.com/2019/05/23/neighbor-polygons-aggregate-qgis/>`_

مواردی وجود دارد که می خواهید همه چند ضلعی های مجاور هر چند ضلعی را در یک لایه پیدا کنید. با کمی اسکریپت پایتون، می‌توانیم این کار و خیلی بیشتر را در QGIS انجام دهیم. در اینجا یک نمونه اسکریپت وجود دارد که می توانید از آن برای یافتن همه چند ضلعی هایی که با هر چند ضلعی در یک لایه مرز مشترک دارند و همچنین نام آنها را به جدول ویژگی اضافه کنید، استفاده کنید. به عنوان یک امتیاز اضافی، اسکریپت همچنین یک ویژگی انتخابی شما را از همه چند ضلعی های همسایه خلاصه می کند.

بررسی اجمالی کار

برای نشان دادن نحوه عملکرد اسکریپت، از لایه ای از چند ضلعی های کشور استفاده می کنیم و کشورهایی را که مرز مشترک دارند، پیدا می کنیم. ما همچنین می خواهیم کل جمعیت همسایگان کشور را محاسبه کنیم.

داده ها را دریافت کنید

ما از مجموعه داده "Admin 0 - Countries <http://www.naturalearthdata.com/downloads/10m-cultural-vectors/10m-admin-0-countries/>"_ از Natural Earth استفاده خواهیم کرد.

فایل شکل فایل «Admin 0 - Country» را دانلود کنید. <http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_0_countries.zip>`_.

منبع داده [NATURALEARTH]

فیلمنامه را دریافت کنید

اسکریپت :download:`neighbors.py را دانلود کنید و آن را در دیسک خود ذخیره کنید.

روش

  1. لایه «ne_10m_admin_0_countries» را با رفتن به Layer ‣ Add Vector Layer بارگیری کنید.

../_images/1182.png
  1. اسکریپت از 2 فیلد برای انجام عمل استفاده می کند. یک فیلد نام و یک فیلد که می خواهید خلاصه کنید. از ابزار :guilabel:`Identify برای کلیک بر روی هر ویژگی و بررسی ویژگی ها استفاده کنید. در این مورد، فیلد نام NAME است و می‌خواهیم برآوردهای جمعیت را از قسمت POP_EST جمع‌بندی کنیم.

../_images/2149.png
  1. به :menuselection:`Plugins --> Python Console بروید.

../_images/389.png
  1. در پنجره :guilabel:'Python Console'، روی دکمه :guilabel:'Show Editor' کلیک کنید.

../_images/456.png
  1. در پانل :guilabel:'Editor'، روی دکمه :guilabel:'Open file' کلیک کنید و اسکریپت "neighbors.py" دانلود شده را مرور کنید و روی :guilabel:"Open" کلیک کنید.

../_images/549.png
  1. پس از بارگیری اسکریپت، ممکن است بخواهید مقادیر "_NAME_FIELD" و "_SUM_FIELD" را تغییر دهید تا با ویژگی های لایه خود مطابقت داشته باشد. اگر با لایه «ne_10m_admin_0_countries» کار می‌کنید، می‌توانید آن‌ها را همانطور که هستند رها کنید. اگر تغییری ایجاد کردید، روی دکمه Save در پنل Editor کلیک کنید. اکنون روی دکمه :guilabel:`Run script کلیک کنید تا اسکریپت اجرا شود.

../_images/647.png
  1. پس از اتمام اسکریپت، روی لایه "ne_10m_admin_0_countries" کلیک راست کرده و :guilabel:"Open Attribute Table" را انتخاب کنید.

../_images/747.png
  1. متوجه 2 ویژگی جدید به نام‌های «همسایه» و «جمع» خواهید شد. اینها توسط فیلمنامه اضافه شد.

../_images/846.png

در زیر اسکریپت کامل برای مرجع آورده شده است. شما می توانید آن را مطابق با نیاز خود تغییر دهید.

################################################################################
# Copyright 2014 Ujaval Gandhi
#
#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#
################################################################################
from qgis.utils import iface
from PyQt4.QtCore import QVariant

# Replace the values below with values from your layer.
# For example, if your identifier field is called 'XYZ', then change the line
# below to _NAME_FIELD = 'XYZ'
_NAME_FIELD = 'NAME'
# Replace the value below with the field name that you want to sum up.
# For example, if the # field that you want to sum up is called 'VALUES', then
# change the line below to _SUM_FIELD = 'VALUES'
_SUM_FIELD = 'POP_EST'

# Names of the new fields to be added to the layer
_NEW_NEIGHBORS_FIELD = 'NEIGHBORS'
_NEW_SUM_FIELD = 'SUM'

layer = iface.activeLayer()

# Create 2 new fields in the layer that will hold the list of neighbors and sum
# of the chosen field.
layer.startEditing()
layer.dataProvider().addAttributes(
        [QgsField(_NEW_NEIGHBORS_FIELD, QVariant.String),
         QgsField(_NEW_SUM_FIELD, QVariant.Int)])
layer.updateFields()
# Create a dictionary of all features
feature_dict = {f.id(): f for f in layer.getFeatures()}

# Build a spatial index
index = QgsSpatialIndex()
for f in feature_dict.values():
    index.insertFeature(f)

# Loop through all features and find features that touch each feature
for f in feature_dict.values():
    print 'Working on %s' % f[_NAME_FIELD]
    geom = f.geometry()
    # Find all features that intersect the bounding box of the current feature.
    # We use spatial index to find the features intersecting the bounding box
    # of the current feature. This will narrow down the features that we need
    # to check neighboring features.
    intersecting_ids = index.intersects(geom.boundingBox())
    # Initalize neighbors list and sum
    neighbors = []
    neighbors_sum = 0
    for intersecting_id in intersecting_ids:
        # Look up the feature from the dictionary
        intersecting_f = feature_dict[intersecting_id]

        # For our purpose we consider a feature as 'neighbor' if it touches or
        # intersects a feature. We use the 'disjoint' predicate to satisfy
        # these conditions. So if a feature is not disjoint, it is a neighbor.
        if (f != intersecting_f and
            not intersecting_f.geometry().disjoint(geom)):
            neighbors.append(intersecting_f[_NAME_FIELD])
            neighbors_sum += intersecting_f[_SUM_FIELD]
    f[_NEW_NEIGHBORS_FIELD] = ','.join(neighbors)
    f[_NEW_SUM_FIELD] = neighbors_sum
    # Update the layer with new attribute values.
    layer.updateFeature(f)

layer.commitChanges()
print 'Processing complete.'

If you want to give feedback or share your experience with this tutorial, please comment below. (requires GitHub account)