Процент многоугольника в одном шейп-файле внутри другого многоугольника


13

Я новичок, извиняюсь, если это очевидно / уже спросили и ответили, но я не смог ничего найти.

У меня есть два шейп-файла: 1. административный пограничный слой для округа в Великобритании, известного как граница LSOA, в котором есть 500 небольших зон 2. зона затопления.

В идеале я хочу выяснить, какие из небольших зон LSOA составляют ≥50% в зоне затопления, и в итоге получим да / нет или 1/0 для каждой из 500 зон LSOA.

Но я не знаю, как это сделать. Я подумал, что могу объединить два шейп-файла, но между ними нет общего атрибута. Тогда я подумал, что мог бы использовать функцию «Атрибут соединения по местоположению», которая работала и показывала мне, какие LSOA находятся в зоне затопления, но это почти все из них (см. Изображение 2).

Я думаю, что это проблема SQL, но я не знаю. Я новичок в QGIS и никогда не использовал PostgreSQL.

Любая помощь будет принята с благодарностью. Я могу предоставить любую информацию, что вам, милые люди, помогут мне.

введите описание изображения здесь

введите описание изображения здесь

Ответы:


11

Это относительно простая задача с использованием инструментов геообработки, включенных в QGIS.

  1. Рассчитайте площадь ваших зон LSOA.

    • Откройте таблицу атрибутов слоя LSOA.
    • Включить режим редактирования.
    • Откройте калькулятор поля.
    • Создайте новое поле типа «Десятичное число (действительное)» с выражением «$ area».
    • Отключить режим редактирования (сохранение правок).
  2. Объедините слой зоны затопления в один элемент из нескольких частей.

    • Vector > Geometry Tools > Singleparts to Multipart,
    • Выберите «--- Объединить все ---» в поле «Уникальный идентификатор».
  3. Пересечь слой зоны LSOA со слоем многочастной зоны затопления.

    • Vector > Geoprocessing Tools > Intersect,
    • Входной слой - зоны LSOA, пересеченный слой - зоны затопления.
  4. Получающийся слой будет частями зон LSOA (с атрибутами из слоя зон LSOA), которые перекрываются со слоем зон затопления. Чтобы рассчитать долю каждой зоны LSOA в зоне затопления:

    • Рассчитайте площадь пересеченных объектов (как на шаге 1), затем
    • Добавьте еще одно поле, разделив исходную (общую) площадь на пересеченную область. Результат - десятичное число от 0 до 1. Умножьте на 100, чтобы получить процент.
  5. Соедините исходный слой LSOA с пересеченным слоем, используя уникальный идентификатор, общий для обоих слоев.

  6. Экспортируйте объединенный слой как новый шейп-файл.

  7. Удалите дублированные атрибуты.

И вуаля!

Без шага № 2 будет создан отдельный объект для каждого отдельного объекта зоны затопления для каждого объекта LSOA. Это, вероятно, не то, что вы хотите, если вы заинтересованы только в общем покрытии для каждой зоны LSOA. Если вы хотите провести различие между речным / приливным / плювиальным затоплением (и данные зоны затопления поддерживают это), вы можете преобразовать одночастные в многочастные, указав поле «ТИП» в качестве поля уникального идентификатора.


Спасибо за помощь! Очень признателен. Однако у меня возникли некоторые проблемы. Я следовал за шагами. Шаг 3, Пересечение, занял 10 часов, и когда он был сделан, все, что я получил, было пустым шейп- файлом : i.imgur.com/QIM6Gtg.png Есть что-то, что я пропустил? Я попытался завершить процесс и выполнить шаг 4, но нет данных для расчета площади пересечения.
KJGarbutt

У меня были проблемы с пересечением слоев затопления. Особенности большие и сложные. В прошлом я работал над этим, разбивая их на более мелкие объекты, чтобы пространственный индекс мог выполнять большую часть работы. Для этого создайте векторную сетку того же экстента, что и слой затопления ( Vector > Research Tools > Vector Grid... Output grid as polygons), а затем пересекайте сетку со слоем затопления. Затем используйте вывод вместо слоя потока в шаге 3. Я предполагаю, что причина, по которой слой был пуст, заключается в том, что он потерпел крах.
Снорфалорпагус

Еще раз спасибо. Единственная проблема сейчас в том, что QGIS падает каждый раз, когда я пытаюсь создать векторную сетку. Я следовал совету отсюда, но он каждый раз падает. Я несколько раз менял параметры и пытался использовать только шейп-файл зоны затопления, вместо того, чтобы открыть весь файл моего проекта, и он каждый раз терпел неудачу. Есть идеи? ! Скриншот здесь .
KJGarbutt

Заданные вами параметры X и Y слишком малы. Попробуйте что-то вроде 1000 x 1000. Вы можете даже сделать это несколько раз, то есть сначала сделать 5000 x 5000, использовать выходные данные для создания 500 x 500. См. Связанный ответ здесь: gis.stackexchange.com/a/66319/12420
Snorfalorpagus

Я чуть не сломал его с твоей помощью! Однако, когда я присоединяюсь к исходному слою LSOA с пересеченным слоем, я теряю много данных. Я думаю, это потому, что некоторые из созданных векторных квадратов сетки находятся в одной области LSOA и поэтому имеют одинаковый код LSOA для каждого. Таким образом, я получаю 2+ процентных показателя для каждой области LSOA, когда я выполняю объединение, и я, кажется, получаю только один из них. Есть ли способ суммировать каждый процент для каждого квадрата векторной сетки с одним и тем же LSOA?
KJGarbutt

6

Вы можете использовать пространственный и некоторые пространственные функции SQL.

Select t1.geometry, t1.ID, area(t1.geometry), area(t2.geometry) ...... (anything you need to have in the table results)

(area(intersection(t1.geometry,t2.geometry))) as "Commun_AREA"

, ("Commun_AREA"*100/(area(t1.geometry))) as "Percent_AREA"

From lsoa as t1, flood_zone as t2

Where Intersects( t1.geometry,t2.geometry ) = 1

3

Это похоже на то, что можно сделать гораздо проще, чем ответы. Я бы лично использовал простой скрипт на python:

floodName = "the layer name here"
boundryName = "the layer name here"
fieldName = "the name of the field to contain the output 1/0"
minCoverage = 0.5 # the minimum amount of area covered to write 1
updateMap = [] # this will store values to be written    

# get layers
floodLayer = QgsMapLayerRegistry.instance().mapLayersByName(floodName)[0]
boundryLayer = QgsMapLayerRegistry.instance().mapLayersByName(boundryName)[0]
fieldIndex = boundryLayer.dataProvider().fieldNameIndex(fieldName)    

# iterate through boundries
for b in boundryLayer.getFeatures():
    # get only flood features that intersect with this feature's bounding box
    # this will make the script go way faster than it would otherwise
    request = QgsFeatureRequest().setFilterRect(b.geometry().boundingBox())
    floodGeom = geometry()
    floodFeat = QgsFeature()
    iter = floodLayer.getFeatures(request)
    iter.nextFeature(feat)
    while iter.nextFeature(feat):
        floodGeom = floodGeom.combine(feat.geometry())
    intersectGeom = b.geometry().intersection(feat.geometry())
    if intersectGeom.area() > minCoverage * b.geometry().area():
        updateMap[b.id()] = {fieldIndex : 1}
    else:
        updateMap[b.id()] = {fieldIndex : 0}

boundryLayer.dataProvider().changeAttributeValues(updateMap)

это только оценивает полигоны затопления, которые пересекаются с ограничивающей рамкой каждого пограничного слоя, поэтому он должен быть достаточно быстрым для запуска, тогда он обновляет только одно поле в существующем слое (вместо сложной операции создания целого нового слоя и копирования старых значений). потом удаляю)


2

У меня была та же проблема, что и у KJ, следовавшего инструкциям Snorfalorpagus с использованием метода «Пересечение» на шаге 3. Потребовалось довольно много времени, чтобы рассчитать, и то, что у меня осталось, было пустым.

Я попытался выполнить те же шаги, за исключением того, что использовал метод «Клип» в QGIS вместо Intersect - так что, в вашем примере, остались бы части областей, которые НЕ покрыты зоной затопления. По какой-то причине это сработало, и я смог использовать расчет поля «Площадь» из предыдущего шага, а также новый расчет «Площадь» для оставшихся частей каждого многоугольника, чтобы вычислить% каждой области, которая НЕ была покрыты другим слоем полигона.

Технически, это то, что вы просили. Но оттуда это просто вопрос вычитания каждого значения от 1 , чтобы получить то , что будет покрыто зоной затопления.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.