Ich wurde kürzlich in einem Schulungskurs gefragt, ob QGIS die nächsten / vorherigen und oberen / unteren Seitenzahlen für ein mit dem Atlasgenerator erstelltes Kartenbuch automatisch berechnen kann. Ich habe es geschafft, einen ziemlich vernünftigen Beschriftungsausdruck für ein reguläres Raster zu erarbeiten, wenn Sie die Breite und Höhe des Rasters kennen.
Aber dann haben wir uns realistische Beispiele ausgedacht, bei denen wir keine Seiten zeichnen möchten, die nicht unseren interessierenden Bezirk enthalten, wie diesen aus meinem Heimatland:
Also habe ich heute Nachmittag ein Python-Skript gespielt, um die 4 Nachbarn, an denen ich interessiert war, für jede Gitterzelle herauszufinden und diese Werte zu meinem Gitter hinzuzufügen (dies basiert stark auf Ujaval Gandhis 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()
Das funktioniert gut.
Aber um ehrlich zu sein, scheint es falsch, das Ganze einen Testpunkt nach Norden zu schaffen und dann alle möglichen Nachbarn zu testen. Nach einem Nachmittag, an dem ich mir das Gehirn zerbrochen habe, kann ich mir keinen besseren Weg vorstellen, um festzustellen, was der nördliche Nachbar einer bestimmten Gitterzelle ist.
Idealerweise hätte ich gerne etwas, das einfach genug ist, um es in ein Textfeld für Druckkomponisten einzufügen, aber ich vermute, das ist zu viel verlangt.
quelle
Antworten:
Wenn Sie nicht jede Seitenausdehnung (von der Indexebene) genau in den Composer einpassen, sondern überlappende Ränder mit benachbarten Seiten haben (wie in Ihrem zweiten Screenshot gezeigt), können Sie Beschriftungen aus der Indexebene verwenden, mit dem Nachteil, dass Sie würden sich innerhalb der Kartengrenze befinden.
Wenn es keine Überlappung gibt, können Sie eine Technik, die ich in der Vergangenheit erfolgreich angewendet habe (zufällig in E & W Sussex!), In MapInfo replizieren, wo ich ein kleines Skript geschrieben habe, das für jedes Index-Feature einen Satz von vier Punkten generiert , in die angrenzenden Features versetzt, mit Attributen sowohl der Blattnummer als auch der Versatzrichtung. Die Punktebene wurde dann verwendet, um erneut Beschriftungen zu erzeugen, wobei die Richtung des Versatzes es ermöglichte, die Ausrichtung der Beschriftungen für einen schöneren Effekt anzupassen.
Ich habe dies nicht versucht, aber Sie können möglicherweise vermeiden, eine separate Datenschicht in QGIS zu generieren, indem Sie die neue Geometriegenerator-Styling-Funktion verwenden. Dies würde zu einer eleganteren und dynamischeren Lösung führen, die in MapInfo nicht erreichbar war!
quelle
Tatsächlich haben Sie bereits den größten Teil der erforderlichen Arbeit geleistet, um die Kacheln zu bestimmen, die Sie mit Atlas drucken möchten. Der Punkt ist jedoch, wie Sie alles zusammen anpassen, um nur die Kachel-IDs anzuzeigen, die Sie benötigen. Um meine Idee zu demonstrieren, werde ich in diesem Beispiel ein DEM-Bild und eine Gittervektordatei verwenden, wie Sie unten sehen können:
Zuerst müssen wir die Beschriftung jedes Gitters zeigen.
In der Layoutansicht habe ich das Raster als Abdeckungsebene im Atlas verwendet und zwei Karten erstellt: die Hauptfensterkarte und eine Indexkarte, die nur das Raster anzeigt, wie Sie unten sehen können:
Dann habe ich folgendes gemacht:
Preview atlas
wirdOverview
, um den Umfang und die Position der Hauptansichtskarte zu sehen, wie Sie unten sehen können:Für die Hauptfensterkarte habe ich den Maßstab auf die Ausdehnung jedes Rasterblocks festgelegt, um sicherzustellen, dass der Maßstab nicht geändert wird, wenn etwas passiert, wie Sie unten sehen können.
Mithilfe einer Indexkarte können Sie die ID und Position jeder Kachel in Bezug auf eine andere Kachel leicht anzeigen, selbst wenn Sie das Raster im Hauptfenster der Ansichtskarte ausschalten. Die folgende Karte hat beispielsweise eine Kachel-ID = 14, und Sie können die umgebenden Kachel-IDs sehen.
Update :
Ich werde meine Antwort aktualisieren, da mir klar wurde, dass Sie den Seitenzahlenindex der umgebenden Layouts und nicht die IDs der umgebenden Layouts anzeigen möchten.
Um das Verständnis des Prozesses zu erleichtern, aktualisiere ich die ID-Nummern in der Indexzuordnung, um die Nummer der Layoutseite anzuzeigen, wie unten gezeigt:
Da die IDs, die ich habe, bei 0 (Null) beginnen, beginnt die ID des ersten auf der Indexkarte angezeigten Rasters bei 3. Daher möchte ich die Seitenzahl so ändern, dass sie bei 1 beginnt, indem ich 2 von der ID-Nummer in Atlas subtrahiere:
Page number: ID -2
Dann verwende ich die aktuelle Seitenzahl als Referenz im Ausdruck, um Beschriftungen für die aktuelle Seite, die vorherige Seite, die nächste Seite, die obere Seite und die untere Seite wie folgt zu erstellen:Die aktuelle Seite enthält diesen Ausdruck im Beschriftungstextfeld:
Current Page Number: [%@atlas_pagename%]
Vorheriger
[%if((@atlas_pagename = 1), Null, '↑ Page Number: ' || (@atlas_pagename - 1))%]
Seitenausdruck : da vor 1 keine Seiten vorhanden sindAusdruck der nächsten Seite:
[%if( (@atlas_pagename = 25), Null, '↓ Page Number: ' || (@atlas_pagename + 1))%]
da nach 25 keine Seiten mehr vorhanden sindUp Page Ausdruck:
[%if((@atlas_pagename <= 6),NULL,'↑ Page Number: ' || (@atlas_pagename -6))%]
da in oberer Richtung keine Seiten vor 6 vorhanden sindAusdruck unter der Seite:
[%if((@atlas_pagename >= 20), Null, '↓ Page Number: ' || (@atlas_pagename + 6))%]
da nach 20 keine Seiten in der unteren Richtung vorhanden sindEinige Ausgabeergebnisse:
quelle
Diese Lösung funktioniert für rechteckige Gitter und ist automatisch (sollte für jedes Szenario funktionieren, ohne etwas manuell anzupassen).
Nehmen wir an, Sie haben ein Raster mit Seitenzahlen. Sie können mein Verarbeitungsskript ausführen, indem Sie die Rasterebene und ihr Seitenzahlfeld als Parameter auswählen. Das Skript erstellt vier Felder (
right, left, above, below
) in der Rasterebene und berechnet die entsprechende Nachbarseiten-ID für jede Rasterzelle. Dann können Sie Ihre Ausdrücke (z. B.[% if( "left" is not NULL, 'to page' || "left", "" ) %]
) verwenden, um Beschriftungen der Nachbarseiten anzuzeigen.Fügen Sie einfach mein Repository ( https://github.com/gacarrillor/QGIS-Resources.git ) vom QGIS Resource Sharing-Plugin hinzu und installieren Sie das Skript:
Wie es funktioniert
Das Skript ermittelt die Beziehung (rechts, links, oben oder unten) durch Vergleichen der Koordinaten der Begrenzungsrahmen sowohl von der aktuellen Gitterzelle als auch von jeder sich überschneidenden Zelle. Es stellt sich heraus, dass für jede Beziehung eine der Koordinaten fehlt.
Wenn die Beziehung ist
above
, ist die fehlende KoordinateyMin
, dh alle anderen 3 Koordinaten aus dem Begrenzungsrahmen der aktuellen Gitterzelle sind im Begrenzungsrahmen der obigen Zelle vorhanden. Beachten Sie, dass die QGIS-Begrenzungsrahmen in dieser Reihenfolge definiert sind :[xMin, yMin, xMax, yMax]
.Nehmen wir für ein numerisches Beispiel Rechtecke mit Seiten der Länge 1. Angenommen, der Begrenzungsrahmen der aktuellen Zelle ist definiert als
bbox1=[0,0,1,1]
. Der Begrenzungsrahmen der obigen Zelle wäre definiert alsbbox2=[0,1,1,2]
. X-Koordinaten von bbox1 sind in bbox2 vorhanden, während bbox1yMin
in Y-Koordinaten von bbox2 fehlen.Wir können unsere 4 Beziehungen auf diese Weise definieren (o: vorhanden, #: fehlt):
Wie Sie sehen können, gibt uns der fehlende Index alle Informationen, die wir benötigen.
quelle