На нещодавньому навчальному курсі мене запитали, чи 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()
Це працює просто чудово.
Але якщо чесно, цілком створюється тестовий пункт на Північ і потім випробовувати всіх можливих сусідів. Однак після того, як після обіду моєму мозку я не можу придумати кращий спосіб визначити, що таке північний сусід тієї чи іншої сітки?
В ідеалі я хотів би щось просте, щоб помістити у текстове поле для друку композитора, але я підозрюю, що це занадто багато, щоб просити.