Чи є спосіб вибрати атрибут з шару багатокутника і вставити значення у віртуальне поле точкового шару, використовуючи "в" в калькуляторі поля?
CASE
WHEN within($geometry, geometry_polygon) THEN attribute_polygon
END
Чи є спосіб вибрати атрибут з шару багатокутника і вставити значення у віртуальне поле точкового шару, використовуючи "в" в калькуляторі поля?
CASE
WHEN within($geometry, geometry_polygon) THEN attribute_polygon
END
Відповіді:
Поле полезний калькулятор не підтримує просторових з'єднань між шарами функції. Але якщо ви подивитесь на публікацію NathanW у редакторі функцій для виразів qgis, ви зможете зрозуміти, що ми можемо скриптувати власну взаємодію з даними.
Наступний сценарій дозволить вам виразити те, що ви хочете. Це працює за допомогою ітерації через всі функції на полігоновому шарі, і якщо є просторове з'єднання, то посилаються табличні дані із зазначеного стовпця:
from qgis.core import *
from qgis.gui import *
from qgis.utils import iface
allfeatures = None
index = QgsSpatialIndex()
indexMade = 0
refLayer = None
@qgsfunction(args="auto", group='Custom')
def spatialJoinLookup(layerName, refColumn, defaultValue, geom, feature, parent):
if geom is None:
return defaultValue
# globals so we don't create the index, refLayer more than once
global allfeatures
global index
global indexMade
global refLayer
# Get the reference layer
if refLayer is None:
for layer in iface.mapCanvas().layers():
if layerName == layer.name():
refLayer = layer
break
if refLayer is None:
raise Exception("Layer [" + layerName + "] not found")
# Create the index if not exists
if indexMade == 0:
index = QgsSpatialIndex()
allAttrs = layer.pendingAllAttributesList()
layer.select(allAttrs)
allfeatures = {feature.id(): feature for (feature) in refLayer.getFeatures()}
for f in allfeatures.values():
index.insertFeature(f)
indexMade = 1
# Use spatail index to find intersect
fid = None
ids = index.intersects(geom.boundingBox())
for id in ids:
fid = id
break # Only get the first match.
if fid is not None:
return allfeatures[fid].attribute(refColumn)
# Default
return defaultValue
Нижче наведено приклад багатокутного шару, який у вас може бути. Я також створив відповідний точковий шар, який ви побачите на фінальному зображенні.
Зауважте, якщо ви хочете використовувати окремий стовпець, ви повинні змінити другий аргумент, щоб він відповідав імені стовпця в наборі даних полігона. Наприклад, ви можете використовувати стовпець «AreaNumber», але вам доведеться відповідати типу стовпця в налаштуваннях калькулятора поля.
Ви можете бачити, що значення стовпця за замовчуванням було застосовано там, де немає просторового з'єднання, а інші співпали з правильними даними. Зауважте, що сценарій, який я дав, приєднається лише до першого матчу. Вам потрібно було б створити іншу логіку бізнесу, якби ваші багатокутники перекривались.
Це можна зробити в Field Calculator з функцією aggregate()
. У точковому шарі створіть нове поле з виразом калькулятора поля таким чином:
aggregate(
layer:= 'polygon_layer_name',
aggregate:='concatenate',
expression:=joining_field_name,
concatenator:=', ',
filter:=intersects($geometry, geometry(@parent))
)
Де layer
назва полігонного шару написана як рядок, aggreagate
є агрегованою функцією (може використовуватися також сума тощо), expression
поле з значень буде взято, concatenator
є приєднанням до рядка символів (повинні бути встановлені, навіть у цьому випадку) і filter
фільтрує функції на основі на експресію (в цьому випадку перетинає геометрію шару з геометрією батьківського шару).
Для отримання додаткової інформації ознайомтеся з документацією щодо сукупності QGIS .
Для автоматичного оновлення можна використовувати віртуальні поля або ви можете встановити вираз як значення за замовчуванням у налаштуваннях форми атрибутів у властивостях шару ( документація щодо налаштування форми атрибутів ).
geometry(@parent)
) підтримуються лише з QGIS 3 і далі. На всякий випадок, коли хтось, хто читає це, все ще використовує 2.18 ...