En un reciente curso de formación me preguntaron si QGIS podía calcular automáticamente los números de página siguiente/anterior y superior/inferior de un libro de mapas creado con el generador de atlas. Conseguí elaborar una expresión de etiqueta bastante razonable para una cuadrícula regular si se conoce la anchura y la altura de la cuadrícula.
Pero luego empezamos a pensar en ejemplos realistas en los que no queremos dibujar páginas que no contengan nuestro distrito de interés, como ésta de mi condado natal:
Así que esta tarde he jugado con un script de Python para calcular los 4 vecinos que me interesaban para cada celda de la cuadrícula y he añadido esos valores a mi cuadrícula (esto se basa en gran medida en Ujaval Gandhi tutorial ):
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()
Esto funciona bien.
Pero, para ser sincero, lo de crear un punto de prueba al norte y luego probar todos los posibles vecinos parece un error. Sin embargo, después de una tarde de devanarse los sesos, no se me ocurre una forma mejor de determinar cuál es el vecino norte de una celda de la cuadrícula.
Lo ideal sería algo lo suficientemente sencillo como para ponerlo en un cuadro de texto del compositor de la impresión, pero sospecho que es demasiado pedir.
0 votos
Qué pasa si no hay ningún vecino en un lado. ¿Quiere que el valor de la celda closeset en una dirección o dejaría un vacío?
0 votos
En ese caso me basta con un null, puedo configurar fácilmente la etiqueta para que sólo se muestre cuando no sea null o esté vacía.
0 votos
¿Cómo es posible que su cuadrícula se nombre de izquierda a derecha en lugar de arriba a abajo? Me gustaría hacer esto también. Incluso mejor, primera línea A, segunda línea B,... y numeración de izquierda a derecha. ¿Es esto posible?
0 votos
@Carina - ver gis.stackexchange.com/questions/330760/