Lors d'un récent cours de formation, on m'a demandé si QGIS pouvait calculer automatiquement les numéros de page suivant / précédent et supérieur / inférieur pour un atlas créé à l'aide du générateur d'atlas. J'ai réussi à trouver une expression d'étiquette assez raisonnable pour une grille régulière si vous connaissez la largeur et la hauteur de la grille.
Mais nous avons ensuite commencé à penser à des exemples réalistes où nous ne voulons pas dessiner des pages qui ne contiennent pas notre district d'intérêt, comme celui de mon comté d'origine:
Cet après-midi, j'ai donc joué à un script python pour déterminer les 4 voisins qui m'intéressaient pour chaque cellule de la grille et j'ai ajouté ces valeurs à ma grille (cela est fortement basé sur le tutoriel d' Ujaval Gandhi ):
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()
Cela fonctionne très bien.
Mais pour être honnête, le tout créant un point de test vers le Nord puis testant tous les voisins possibles semble faux. Cependant, après un après-midi à me casser la tête, je ne peux pas penser à une meilleure façon de déterminer quel est le voisin du nord d'une cellule de grille particulière?
Idéalement, j'aimerais quelque chose d'assez simple à mettre dans une zone de texte de compositeur d'impression, mais je soupçonne que c'est trop demander.