Як визначити сусідні ідентифікатори плитки в QGIS?


11

На нещодавньому навчальному курсі мене запитали, чи QGIS може автоматично обчислити наступні / попередні та вище / нижче номери сторінок для карти карт, створеної за допомогою генератора атласу. Мені вдалося розробити досить розумний вираз мітки для звичайної сітки, якщо ви знаєте ширину та висоту сітки.

Але тоді ми почали думати про реалістичні приклади, коли ми не хочемо малювати сторінки, які не містять наш район інтересу, наприклад, цей мій округ:

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

Тож сьогодні вдень я зіграв за сценарієм пітона, щоб опрацювати 4 сусідів, які мене зацікавили для кожної комірки сітки, і додав ці значення до моєї сітки (це ґрунтується на підручнику Уджавала Ганді ):

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]
        int_geom = intersecting_f.geometry()
        centroid = geom.centroid()
        height = geom.boundingBox().height()
        width = geom.boundingBox().width()
        # 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 int_geom.disjoint(geom)):
            above_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()+height))
            below_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x(),
               centroid.asPoint().y()-height))
            left_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()-width,
               centroid.asPoint().y()))
            right_point = QgsGeometry.fromPoint(QgsPoint(centroid.asPoint().x()+width,
               centroid.asPoint().y()))
            above = int_geom.contains(above_point)   
            below = int_geom.contains(below_point)   
            left = int_geom.contains(left_point)
            right = int_geom.contains(right_point)
            if above:
                print "setting %d as above %d"%(intersecting_f['id'],f['id'])
                f['above']=intersecting_f['id']

            if below:
                print "setting %d as below %d"%(intersecting_f['id'],f['id'])
                f['below']=intersecting_f['id']

            if left:
                print "setting %d as left of %d"%(intersecting_f['id'],f['id'])
                f['left']=intersecting_f['id']

            if right:
                print "setting %d as right of %d"%(intersecting_f['id'],f['id'])
                f['right']=intersecting_f['id']

    # Update the layer with new attribute values.
    layer.updateFeature(f)

layer.commitChanges()

Це працює просто чудово.

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

Але якщо чесно, цілком створюється тестовий пункт на Північ і потім випробовувати всіх можливих сусідів. Однак після того, як після обіду моєму мозку я не можу придумати кращий спосіб визначити, що таке північний сусід тієї чи іншої сітки?

В ідеалі я хотів би щось просте, щоб помістити у текстове поле для друку композитора, але я підозрюю, що це занадто багато, щоб просити.


що робити, якщо немає сусіда з одного боку. Ви хочете, щоб значення комірки набору було в одному напрямку або ви залишите порожнечу?
radouxju

Я щасливий за нуль у такому випадку, можу легко встановити мітку, щоб вона відображалася лише тоді, коли вона не є нулевою або порожньою.
Ян Тертон

Відповіді:


3

Якщо ви не вписуєте кожен розмір сторінки (із рівня індексу) саме в композитор, а натомість маєте перекриття меж із суміжними сторінками (як показано на другому скріншоті), то ви можете використовувати мітки із рівня індексу, з нижчою стороною, що вони опиняться всередині кордону карти.

Якщо немає жодного перекриття, ви можете повторити техніку, яку я успішно використовував у минулому (збіг випадків у E&W Sussex!) У MapInfo, де я написав невеликий сценарій, який створив набір з чотирьох балів для кожної функції індексу , зміщення в суміжні ознаки з атрибутами як номера аркуша, так і напрямку зміщення. Потім точковий шар використовувався для повторного генерування міток, при цьому напрямок зміщення дозволяє регулювати орієнтацію міток для кращого ефекту.

Я цього не пробував, але, можливо, ви зможете уникнути генерації окремого рівня даних у QGIS завдяки використанню нового функціонального стилю генератора геометрії, це дозволить зробити більш елегантне та динамічне рішення, яке не було досяжним у MapInfo!


Я дійсно мав би подумати просто про використання міток інших багатокутників! :-) Після швидкого експерименту з генератором геометрії я можу намалювати обмежувальний ящик, але скласти сітку важче
Ian Turton

Я думав по лінії створення точок мітки, зміщених у сусідні багатокутники, а не в сітки. Іншим варіантом буде розширення MBR функції індексу на суміжні функції, щоб дозволити малювати мітки.
Енді Гарфут

Просто відбулася гра, і, здається, геометрія, створена стилем генератора геометрії, не має маркування, тому не є більш елегантним рішенням, на яке я сподівався.
Енді Гарфут

8

Насправді ви вже зробили більшу частину роботи, необхідної для визначення плитки, яку ви хочете надрукувати за допомогою атласу. Але справа в тому, як налаштувати все разом, щоб показати лише ідентифікатори плитки, які вам потрібні. Щоб продемонструвати свою ідею, я використаю в цьому прикладі зображення DEM і векторний файл сітки, як ви бачите нижче:

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

Спочатку нам потрібно показати мітку кожної сітки.

У поданні макета я використовував сітку як шар покриття в атласі, я створив дві карти: головну віконну карту перегляду та індексну карту, що показує лише сітку, як ви бачите нижче:

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

Тоді я зробив наступне:

  1. Я скоригував шкалу індексної карти, щоб відобразити всю масштабність сітки, а потім зафіксував шкалу
  2. Я зафіксував міру перегляду, щоб запобігти панорамуванню карти під час використання Preview atlasта
  3. Я дозволив Overviewпобачити масштаби та розташування основної карти подання, як ви бачите нижче:

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

На вікні основної карти перегляду я зафіксував масштаб в межах кожного блоку сітки, щоб бути впевненим, що масштаб не зміниться, якщо щось трапиться, як ви бачите нижче;

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

Використовуючи індексну карту, ви можете легко побачити ідентифікатор та розташування кожної плитки з посиланням на іншу плитку, навіть коли вимкнете сітку з головного вікна карти перегляду. Наприклад, на наступній карті є ідентифікатор плитки = 14, і ви можете бачити оточуючі ідентифікатори плитки.

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

Оновлення :

Я оновлю свою відповідь, бо зрозумів, що ви хочете показати індекс номера сторінки навколишніх макетів, а не ідентифікатори навколишніх макетів.

Щоб полегшити розуміння процесу, я оновлю ідентифікаційні номери на карті індексу, щоб показати номер сторінки макета, як показано нижче:

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

Оскільки ідентифікатори, які у мене починаються з 0 (нульових), ідентифікатор першої сітки, показаної на карті індексу, починається з 3. Тому я хочу змінити номер сторінки на 1, віднісши 2 від ідентифікаційного номера в Atlas: Page number: ID -2, тоді я буду використовувати номер поточної сторінки в якості посилання в виразі, щоб створити мітки для поточної сторінки, попередньої сторінки, наступної сторінки, верхньої сторінки та нижче сторінки:

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

  • Поточна сторінка має цей вираз у текстовому полі мітки: Current Page Number: [%@atlas_pagename%]

  • Попередній вираз сторінки: [%if((@atlas_pagename = 1), Null, '↑ Page Number: ' || (@atlas_pagename - 1))%]оскільки немає сторінок до 1

  • Наступний вираз сторінки: [%if( (@atlas_pagename = 25), Null, '↓ Page Number: ' || (@atlas_pagename + 1))%]оскільки сторінок немає після 25

  • Вираз сторінки вгору: [%if((@atlas_pagename <= 6),NULL,'↑ Page Number: ' || (@atlas_pagename -6))%]оскільки у верхньому напрямку немає сторінок перед 6

  • Нижче вираз сторінки: [%if((@atlas_pagename >= 20), Null, '↓ Page Number: ' || (@atlas_pagename + 6))%]оскільки у нижньому напрямку немає сторінок після 20

Деякі результати:

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

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

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

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


Хоча корисно, але це не відповідає на його запитання.
Віктор

@Victor Дякую за ваш коментар, я оновив свою відповідь.
ахмадханб

це працює у вашому прикладі (та його), оскільки сторони мапи / сітки регулярні. Якби вони не були прямими, це не спрацювало б, оскільки число, яке потрібно додати або відняти (6 у вашому прикладі), буде змінюватися залежно від сторінки атласу, на якій ви перебуваєте.
Віктор

2
Я погоджуюсь з тобою. Якщо сітка не є регулярною, процес буде складнішим. Але оскільки він хоче застосувати його до звичайної сітки, метод, застосований у запропонованому нами рішення, буде працювати.
ахмадханб

просто зазначивши факт, якщо ви маєте ще одну гарну ідею! Тим більше, що моя сітка не є регулярною!
Віктор

2

Це рішення буде працювати для прямокутних сіток і є автоматичним (має працювати для будь-якого сценарію, не змінюючи нічого вручну).

Припустимо, у вас є сітка з номерами сторінок. Ви можете запустити мій сценарій обробки, вибравши в якості параметрів шар сітки та номер номера сторінки. Сценарій створює чотири поля ( right, left, above, below) у шарі сітки та обчислює відповідний ідентифікатор сторінки сусідньої сторінки для кожної комірки сітки. Тоді ви можете використовувати свої вирази (наприклад, [% if( "left" is not NULL, 'to page' || "left", "" ) %]) для показу міток сусідньої сторінки.

Просто додайте моє сховище ( https://github.com/gacarrillor/QGIS-Resources.git ) із плагіна QGIS Resource Sharing та встановіть сценарій: введіть тут опис зображення

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

Як це працює

Сценарій визначає співвідношення (праворуч, ліворуч, зверху чи знизу), порівнюючи координати обмежувальних коробок як із поточної комірки сітки, так і кожної комірки, що перетинається. Виявляється, що для кожного відношення відсутня одна з координат.

Якщо співвідношення є above, то відсутня координата є yMin, тобто всі інші 3 координати з обмежувального вікна осередку поточної сітки будуть присутні у вищевказаному обмежувальному вікні комірки. Пам'ятайте , що QGIS обмежує коробки визначаються в такому порядку: [xMin, yMin, xMax, yMax].

Для числового прикладу візьмемо прямокутники зі сторонами довжини 1. Скажімо, що обмежувальне поле поточної комірки визначається як bbox1=[0,0,1,1]. Наведене вище обмежувальне поле для комірок визначатиметься як bbox2=[0,1,1,2]. У координаті bbox2 присутні X координати від bbox1, тоді як у bbox1 yMinвідсутні координати Y bbox2.

Ми можемо визначити наші 4 відносини таким чином (o: присутній, #: відсутній):

right: [#,o,o,o]
above: [o,#,o,o]
left:  [o,o,#,o]
below: [o,o,o,#]

Як бачимо, відсутній індекс дає нам всю необхідну нам інформацію.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.