В ходе недавнего учебного курса меня спросили, может ли QGIS автоматически рассчитать номера страниц следующего / предыдущего и выше / ниже для книги карт, созданной с использованием генератора атласа. Мне удалось выработать довольно разумное выражение метки для обычной сетки, если вы знаете ширину и высоту сетки.
Но затем мы начали думать о реалистичных примерах, когда мы не хотим рисовать страницы, которые не содержат интересующую нас область, например, в моем округе:
Поэтому во второй половине дня я была игра на питон скрипт для работы из 4 -х соседей я был заинтересован в каждой ячейку сетки и добавлены эти значения в мою сетку (это в значительной степени основывается на Ujaval Ганди учебника ):
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()
Это работает просто отлично.
Но, честно говоря, создание контрольной точки на севере, а затем проверка всех возможных соседей кажется неправильным. Однако после полудня, потрясшего мой мозг, я не могу придумать лучшего способа определить, кто является северным соседом конкретной ячейки сетки?
В идеале я хотел бы, чтобы что-то достаточно простое поместило в текстовое поле для печати, но я подозреваю, что это слишком много, чтобы просить.
источник
Ответы:
Если вы не вписываете каждый экстент страницы (из слоя индекса) точно в композитор, а вместо этого имеете перекрывающиеся границы со смежными страницами (как показано на втором снимке экрана), то вы можете использовать метки из слоя индекса, с обратной стороной, которая они будут внутри границы карты.
Если нет совпадений, вы можете воспроизвести технику, которую я успешно использовал в прошлом (по совпадению в E & W Sussex!), В MapInfo, где я написал небольшой скрипт, который генерировал набор из четырех точек для каждой функции индекса , смещение на соседние объекты, с атрибутами как номера листа, так и направления смещения. Затем точечный слой снова использовался для создания меток, причем направление смещения позволяло регулировать ориентацию меток для получения более приятного эффекта.
Я не пробовал этого, но вы можете избежать создания отдельного слоя данных в QGIS за счет использования новой функциональности стилей генератора геометрии, это сделало бы более элегантное и динамичное решение, которого не было в MapInfo!
источник
На самом деле вы уже выполнили большую часть работы, необходимой для определения листов, которые вы хотите напечатать, используя атлас. Но дело в том, как настроить все вместе, чтобы показывать только те идентификаторы плиток, которые вам нужны. Чтобы продемонстрировать свою идею, я буду использовать в этом примере изображение матрицы высот и векторный файл сетки, как вы можете видеть ниже:
Сначала нам нужно показать метку каждой сетки.
В представлении макета я использовал сетку в качестве слоя покрытия в атласе, я создал две карты: карту окна основного вида и карту индекса, которая показывает только сетку, как вы можете видеть ниже:
Затем я сделал следующее:
Preview atlas
, и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 страниц нетUp Выражение страницы:
[%if((@atlas_pagename <= 6),NULL,'↑ Page Number: ' || (@atlas_pagename -6))%]
так как нет страниц до 6 в верхнем направленииВыражение ниже страницы:
[%if((@atlas_pagename >= 20), Null, '↓ Page Number: ' || (@atlas_pagename + 6))%]
поскольку после 20 в нижнем направлении нет страницНекоторые выходные результаты:
источник
Это решение будет работать для прямоугольных сеток, и оно автоматическое (должно работать для любого сценария без каких-либо настроек вручную).
Предположим, у вас есть сетка с номерами страниц. Вы можете запустить мой скрипт обработки, выбрав в качестве параметров слой сетки и его поле номера страницы. Сценарий создает четыре поля (
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]
. Координаты X из bbox1 присутствуют в bbox2, тогда как координаты bbox1yMin
отсутствуют в координатах Y в bbox2.Мы можем определить наши 4 отношения следующим образом (o: present, #: missing):
Как видите, отсутствующий индекс дает нам всю необходимую нам информацию.
источник