Creare luci di settore in QGIS?


24

Sto usando QGIS 2.18. Devo creare luci di settore a scopo di navigazione su una mappa.

Ho i dati del settore leggero come campi che danno becon_id, grado iniziale, grado finale e colore in un file di forma con oltre 500 boe, fari e fari che devono essere mostrati sulla mappa. Per ogni faro, possono esserci più file, ognuna delle quali descrive un settore luminoso (ad esempio un settore bianco)

Il risultato finale dovrebbe essere simile al seguente: I settori luminosi nei colori giusti, con il colore contrassegnato come carattere nel campo colore (RGW) e linee tratteggiate da 100 ma 1000 m dalla boa / faro / faro.

Questo dovrebbe probabilmente essere creato come un simbolo basato su regole, ma credo che abbia bisogno di un po 'di pitone?

inserisci qui la descrizione dell'immagine

Di seguito è riportato un esempio dei dati dello shapefile di un faro (purtroppo non quello sopra) che ha un settore verde tra 114 e 154 gradi, un settore bianco tra 154 e 168 gradi, un settore rosso tra 168 e 237 gradi, un verde settore tra 237 e 314 gradi, un settore bianco tra 314 e 320 gradi, un settore rosso tra 320 e 337 gradi (per qualche motivo, 0 non è nord ma sud):

esempio di tabella shapefile



2
Per favore, potresti caricare un set di dati di esempio e modificare la tua domanda elaborando qual è esattamente il risultato che ti aspetti? Nell'immagine allegata vedo solo un universo di simboli e colori.
mgri,

1
I dati di esempio potrebbero essere utili qui. Hai una caratteristica per luce di settore o una caratteristica per boa? Il plug-in Wedge Buffer potrebbe essere utile qui, ma quanto sia facile dipenderà dalla configurazione dei dati.
Steven Kay,

Ciao @mgri e Steven, ho aggiunto dati di esempio e ho cercato di chiarire la domanda :), grazie!
Benjamin Donner

1
@mgri le linee non sono una variabile, ma linee che dovrebbero essere staticamente mostrate come linee lunghe 900m tra i settori luminosi come nell'immagine. Sistema di riferimento previsto.
Benjamin Donner

Risposte:


50

EDIT Ho modificato la risposta per la gestione di situazioni particolari (a causa di valori angolari specifici) e per non visualizzare le linee tratteggiate quando viene definito un angolo arrotondato.


Propongo una soluzione ricorrendo solo alla simbologia e all'etichettatura basate su regole.

Prima di iniziare, voglio sottolineare che focalizzerò l'attenzione sulla spiegazione delle cose minime da fare per riprodurre il risultato desiderato: ciò significa che alcuni altri parametri minori (come dimensioni, larghezze e così via) dovrebbero essere facilmente regolati da te per adattarsi meglio alle tue esigenze.

Inoltre, questa soluzione funziona solo se si assume che il 0grado sia Nord anziché Sud (se 0è Sud, invece, sarebbe sufficiente sommare un 180valore ogni volta che appare un '90' in formule che si occupano di angoli, ad esempio cos(radians(90))diventerebbe cos(radians(180 + 90))). Ho preferito farlo solo per dare una soluzione più generale.


Messa in piega

Renderemo i punti con a Single symbole ricorrendo a uno Simple Markere tre Geometry generatorlivelli simbolo:

inserisci qui la descrizione dell'immagine

Nell'ulteriore spiegazione, seguirò lo stesso ordine dei simboli nell'immagine sopra.

1) Indicatore semplice

Ho scelto un simbolo predefinito di una stella nera (questa è la parte più semplice di questo tutorial), con una dimensione di 3 mm e una larghezza di 0,4 mm.

2) Geometry Generator No. 1

Aggiungi un nuovo livello simbolo e seleziona il Geometry generatortipo:

inserisci qui la descrizione dell'immagine

Inserisci questa espressione nel Expressioncampo:

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

Abbiamo appena definito la prima linea che punta verso il punto da cui parte il settore della luce. Questa linea è lunga 1000 m ed è creata solo quando l'angolo di apertura della luce del settore non è un angolo arrotondato (questo accade per evitare che la linea si spezzerebbe un intero cerchio).

3) Geometry Generator No. 2

Come sopra ma, in questo passaggio, è necessario utilizzare questa espressione:

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

Abbiamo appena definito la prima linea che punta verso il punto in cui finisce il settore leggero. Questa linea è lunga 1000 m ed è creata solo quando l'angolo di apertura della luce del settore non è un angolo arrotondato (questo accade per evitare che la linea si spezzerebbe un intero cerchio).

4) Geometry Generator No. 3

Inserisci questa espressione nel Expressioncampo:

CASE

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
difference(
 boundary(
  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(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
intersection(
 boundary(
  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(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
intersection(
 boundary(
  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(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
difference(
 boundary(
  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(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)


END

Abbiamo appena definito l'arco tra i punti iniziale e finale del settore chiaro (si noti che 2000è un valore arbitrario perché sto cercando di creare un poligono per intersecare il confine del cerchio con un raggio di 900 m).

Inoltre, dobbiamo impostare il colore memorizzato nel "VARIS"campo. Per fare ciò, dobbiamo specificarlo con un'espressione personalizzata. Segui la freccia nell'immagine qui sotto:

inserisci qui la descrizione dell'immagine

e quindi digitare questa espressione dopo aver fatto clic sul Edit...pulsante:

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

Si noti che, per questo layer di simboli, ho creato due righe: la riga superiore definisce il colore da utilizzare (in effetti ho impostato l'espressione personalizzata per questa), mentre quella inferiore è utile per definire un bordo nero (avrà una larghezza maggiore di quella della linea superiore). Ricorda anche di impostare Flatcome Cap styleper entrambe le linee per evitare sovrapposizioni di colore.


etichettatura

1) Impostazione delle etichette

Vai a Layer Properties> Labelse, come al solito, segui le frecce rosse:

inserisci qui la descrizione dell'immagine

e quindi digitare questa espressione:

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

Abbiamo appena definito la regola del colore utilizzando il valore memorizzato nel "VARIS"campo.

2) Impostazione del posizionamento per le etichette

Seleziona l' Placementopzione nel Labelsmenu e seleziona Offset from point.

Quindi, con riferimento all'immagine seguente:

inserisci qui la descrizione dell'immagine

segui la freccia rossa e digita questa espressione:

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

Quindi, segui la freccia verde e digita questa espressione:

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

Risultato finale

Se hai eseguito correttamente le attività precedenti, dovresti essere in grado di ottenere questo risultato:

inserisci qui la descrizione dell'immagine

indennità

Dato che i parametri minori erano troppi per essere completamente coperti da questa risposta, ho allegato lo stile qui : puoi aprire questo codice con qualsiasi editor di testo e salvarlo come file QGIS Layer Style (cioè con .qmlun'estensione).

Lo stile sopra è stato creato usando QGIS 2.18.4 (deve avere lo stesso nome dello shapefile che stai usando).


3
Sembra fantastico, ti mostra davvero la potenza del generatore di geometria. Il rendering è lento?
Heikki Vesanto,

2
@Vesanto L'ho provato su un punto con sei caratteristiche (ovvero sei luci di settore) e il rendering è stato istantaneo. Penso che dovrebbe essere veloce anche quando si hanno a che fare con centinaia di funzionalità perché non c'è chiamata ai provider o qualcosa di simile, ma solo un paio di operazioni matematiche e geometrie come Well Know Text.
mgri

2
Domande / risposte come queste mostrano davvero quanto versatile possa essere QGIS!
Joseph

1
@mgri sei il Maestro, una soluzione straordinariamente buona e una grande spiegazione che richiede molto lavoro, GRAZIE !!
Benjamin Donner,

1
@mgri una montagna in questa regione dovrebbe essere chiamata come te, grazie !! Ho provato un po 'e non sono stati trovati problemi con le tue soluzioni aggiunte :)!
Benjamin Donner,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.