Mehr

Sektorlichter in QGIS erstellen?


Ich verwende QGIS 2.18. Ich muss Sektorlichter für Navigationszwecke auf einer Karte erstellen.

Ich habe die Lichtsektordaten als Felder mit Becon_id, Startgrad, Endgrad und Farbe in einem Shapefile mit über 500 Bojen, Beacons und Leuchttürmen, die auf der Karte angezeigt werden müssen. Für jede Bake kann es viele Zeilen geben, die jeweils einen Lichtsektor beschreiben (z. B. einen weißen Sektor)

Das Endergebnis sollte ungefähr wie folgt aussehen: Die Lichtsektoren in den richtigen Farben, wobei die Farbe als Zeichen im Farbfeld (R G W) markiert ist, und gepunktete Linien von 100 m bis 1000 m von der Boje/Leuchtfeuer/Leuchtturm.

Dies sollte höchstwahrscheinlich als regelbasiertes Symbol erstellt werden, braucht aber wohl etwas Python?

Hier unten ist ein Beispiel für die Shapefile-Daten für einen Leuchtturm (leider nicht der obige), der einen grünen Sektor zwischen 114 und 154 Grad hat, einen weißen Sektor zwischen 154 und 168 Grad, einen roten Sektor zwischen 168 und 237 Grad, ein grünes Sektor zwischen 237 und 314 Grad, ein weißer Sektor zwischen 314 und 320 Grad, ein roter Sektor zwischen 320 und 337 Grad (aus irgendeinem Grund ist 0 nicht Norden, sondern Süden):


BEARBEITEN Ich habe die Antwort bearbeitet, um bestimmte Situationen (aufgrund bestimmter Winkelwerte) zu verwalten und die gepunkteten Linien nicht anzuzeigen, wenn ein runder Winkel definiert ist.


Ich schlage eine Lösung vor, indem ich nur auf regelbasierte Symbologie und Beschriftung zurückgreife.

Bevor ich anfange, möchte ich betonen, dass ich mich auf die Erläuterung der minimalen Schritte konzentrieren werde, die zum Reproduzieren des gewünschten Ergebnisses erforderlich sind: Dies bedeutet, dass einige andere kleinere Parameter (wie Größen, Breiten usw.) leicht von Ihnen angepasst werden sollten für eine bessere Anpassung an Ihre Bedürfnisse.

Außerdem, diese Lösung funktioniert nur, wenn du vermutest das0Grad ist Nord statt Süd (wenn0ist Süden, stattdessen würde es genügen, a . zu summieren180Wert jedes Mal, wenn eine '90' in Formeln erscheint, die sich mit Winkeln befassen, z.cos(Radiant(90))würde werdencos(Radiant(180 + 90))). Ich habe es vorgezogen, dies nur zu tun, um eine allgemeinere Lösung zu geben.


Styling

Wir rendern die Punkte mit aEinzelsymbolund wiederkehrend zu einemEinfache Markierungund dreiGeometriegeneratorSymbolebenen:

Bei der weiteren Erläuterung folge ich der gleichen Reihenfolge der Symbole im obigen Bild.

1) Einfache Markierung

Ich habe ein Standardsymbol eines schwarzen Sterns gewählt (dies ist der einfachere Teil dieses Tutorials), mit einer Größe von 3 mm und einer Breite von 0,4 mm.

2) Geometriegenerator Nr. 1

Fügen Sie einen neuen Symbollayer hinzu und wählen Sie die selectGeometriegeneratorArt:

Fügen Sie diesen Ausdruck in das einAusdruckFeld:

CASE WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360 THEN make_line( $geometry, make_point( $x + 1000*cos(Radiant(90 - "ALKUKULMA")), $y + 1000*sin(Radiant(90 - "ALKUKULMA")) ) ) ENDE

Wir haben gerade die erste Linie definiert, die auf den Startpunkt des Lichtsektors zeigt. Diese Linie ist 1000 m lang und wird nur erstellt, wenn der Öffnungswinkel des Sektorlichts kein runder Winkel ist (dies geschieht, um zu vermeiden, dass die Linie einen ganzen Kreis durchbricht).

3) Geometriegenerator Nr. 2

Wie oben, aber in diesem Schritt müssen Sie diesen Ausdruck verwenden:

CASE WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360 THEN make_line( $geometry, make_point( $x + 1000*cos(Radiant(90 - "LOPPUKULMA")), $y + 1000*sin(Radiant(90 - "LOPPUKULMA")) ) ) ENDE

Wir haben gerade die erste Linie definiert, die auf den Punkt zeigt, an dem der Lichtsektor endet. Diese Linie ist 1000 m lang und wird nur erstellt, wenn der Öffnungswinkel des Sektorlichts kein runder Winkel ist (dies geschieht, um zu vermeiden, dass die Linie einen ganzen Kreis durchbricht).

4) Geometriegenerator Nr. 3

Fügen Sie diesen Ausdruck in das einAusdruckFeld:

CASE WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" >= "LOPPUKULMA" THEN different( border( buffer( $geometry, 900) ), make_polygon( geom_from_wkt( geom_to_wkt( make_line( $geometry, make_point ($x + 2000*cos(Radiant(90 - "ALKUKULMA")), $y + 2000*sin(Radiant((90 - "ALKUKULMA" )))), make_point($x + 2000*cos(Radiant(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(Radiant((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))), make_point($x + 2000* cos(Radiant(90 - "LOPPUKULMA")), $y + 2000*sin(Radiant((90 - "LOPPUKULMA")))), $Geometrie) ) ) ) ) WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" <= "LOPPUKULMA" THEN Kreuzung( border( buffer( $geometry, 900) ), make_polygon( geom_from_wkt( geom_to_wkt( make_line( $geometry, make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(Radiant((90 - "ALKUKULMA" )))), make_point($x + 2000*cos(Radiant(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(Radiant((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))), make_point ($x + 2000*cos(Radiant(90 - "LOPPUKULMA")), $y + 2000*sin(Radiant((90 - "LOPPUKULMA")))), $Geometrie) ) ) ) ) WHEN abs("ALKUKULMA " - "LOPPUKULMA") > 180 AND "ALKUKULMA" >= "LOPPUKULMA" THEN Kreuzung( border( buffer( $geometry, 900) ), make_polygon( geom_from_wkt( geom_to_wkt( make_line( $geometry, make_point($x + 2000*cos (Radiant(90 - "ALKUKULMA" )), $y + 2000*sin(Radiant((90 - "ALKUKULMA" )))), make_point($x - 2000*cos(Radiant(90 - ("LOPPUKULMA" + " ALKUKULMA")/2 )), $y - 2000*sin(Radiant((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))), make_point($x + 2000*cos(Radiant(90 - " LOPPUKULMA")), $y + 2000*sin(Radiant((90 - "LOPPUKULMA")))), $geometry) ) ) ) ) WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 UND "ALKUKULMA" < = "LOPPUKULMA" THEN different( border( buffer( $geometry, 900) ), make_polygon( geom_from_wkt( geom_to_wkt( make_line( $geometry, make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(Radiant((90 - "ALKUKULMA" )))), make_point($x - 2000*cos(Radiant(90 - ("LOPPUK ULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(Radiant((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))), make_point($x + 2000*cos(Radiant (90 - "LOPPUKULMA")), $y + 2000*sin(Radiant((90 - "LOPPUKULMA")))), $Geometrie) ) ) ) ) END

Wir haben gerade den Bogen zwischen dem Start- und Endpunkt des Lichtsektors definiert (bitte beachten Sie, dass2000ist ein willkürlicher Wert, weil ich versuche, a zu erstellen Polygon mit der Grenze des Kreises mit einem Radius von 900 m schneiden).

Außerdem müssen wir die Farbe einstellen, die im"VARIS"Feld. Dazu müssen wir es mit einem benutzerdefinierten Ausdruck angeben. Folgen Sie dem Pfeil im Bild unten:

und geben Sie diesen Ausdruck ein, nachdem Sie auf das geklickt habenBearbeiten…Taste:

CASE WHEN "VARIS" = 'vi' THEN color_rgb(51,160,44) WHEN "VARIS" = 'v' THEN color_rgb(255,255,255) WHEN "VARIS" = 'p' THEN color_rgb(227,26,28) END

Bitte beachten Sie, dass ich für diese Symbolebene zwei Linien erstellt habe: Die obere Linie definiert die zu verwendende Farbe (tatsächlich habe ich den benutzerdefinierten Ausdruck für diese festgelegt), während die untere zum Definieren eines schwarzen Rahmens nützlich ist (sie hat eine Breite, die größer ist als die der oberen Zeile). Denken Sie auch daran, zu setzenEbenwieKappenstilfür beide Linien, um Farbüberlappungen zu vermeiden.


Beschriftung

1) Etiketten setzen

Gehe zuLayereigenschaften>Etikettenund folgen Sie wie gewohnt den roten Pfeilen:

und geben Sie dann diesen Ausdruck ein:

CASE WHEN "VARIS" = 'vi' THEN 'G' WHEN "VARIS" = 'v' THEN 'W' WHEN "VARIS" = 'p' THEN 'R' END

Wir haben gerade die Farbregel mit dem in der"VARIS"Feld.

2) Festlegen der Platzierung für Etiketten

Wähle ausPlatzierungOption in derEtikettenMenü und auswählenVersatz vom Punkt.

Dann mit Bezug auf das Bild unten:

Folgen Sie dem roten Pfeil und geben Sie diesen Ausdruck ein:

CASE WHEN "ALKUKULMA" > "LOPPUKULMA" THEN concat( -1000*cos(Radiant(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)), ',', 1000*sin(Radiant(90 - ("ALKUKULMA " + "LOPPUKULMA")/2)) ) WHEN "ALKUKULMA" <= "LOPPUKULMA" THEN concat( 1000*cos(Radiant(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)), ',', - 1000*sin(Radiant(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)) ) ENDE

Folgen Sie dann dem grünen Pfeil und geben Sie diesen Ausdruck ein:

CASE WHEN "ALKUKULMA" >= "LOPPUKULMA" THEN 180-("ALKUKULMA" + "LOPPUKULMA")/2) WHEN "ALKUKULMA" < "LOPPUKULMA" THEN - (("ALKUKULMA" + "LOPPUKULMA")/2) END

Endergebnis

Wenn Sie die vorherigen Aufgaben korrekt ausgeführt haben, sollten Sie dieses Ergebnis erhalten:

Bonus

Da die Nebenparameter zu viele waren, um in dieser Antwort vollständig behandelt zu werden, habe ich den Stil hier angehängt: Sie können diesen Code mit jedem Texteditor öffnen und als QGIS-Layer-Style-Datei speichern (d. h. mit a.qmlErweiterung).

Der obige Stil wurde erstellt mit QGIS 2.18.4 (Es muss den gleichen Namen wie das von Ihnen verwendete Shapefile haben).