Membuat lampu sektor di QGIS?

24

Saya menggunakan QGIS 2.18. Saya perlu membuat lampu sektor untuk keperluan navigasi di peta.

Saya memiliki data sektor ringan sebagai bidang yang memberikan becon_id, derajat mulai, derajat akhir dan warna dalam suatu shapefile dengan lebih dari 500 pelampung, suar dan mercusuar yang perlu ditampilkan di peta. Untuk setiap suar, mungkin ada banyak baris, masing-masing menggambarkan satu sektor ringan (misalnya sektor putih)

Hasil akhirnya akan terlihat seperti di bawah ini: Sektor cahaya dalam warna yang tepat, dengan warna yang ditandai sebagai karakter dalam bidang warna (RGW), dan garis putus-putus dari 100 m hingga 1000 m dari buoy / suar / mercusuar.

Ini kemungkinan besar harus dibuat sebagai simbol berbasis aturan, tetapi perlu beberapa python kurasa?

masukkan deskripsi gambar di sini

Di bawah ini adalah contoh data shapefile untuk mercusuar (sayangnya bukan yang di atas) yang memiliki sektor hijau antara 114 dan 154 derajat, sektor putih antara 154 dan 168 derajat, sektor merah antara 168 dan 237 derajat, hijau sektor antara 237 dan 314 derajat, sektor putih antara 314 dan 320 derajat, sektor merah antara 320 dan 337 derajat (untuk beberapa alasan, 0 bukan utara tetapi selatan):

contoh tabel shapefile

Benjamin Donner
sumber
2
Tolong, bisakah Anda mengunggah dataset sampel dan mengedit pertanyaan Anda dengan menguraikan apa sebenarnya hasil yang Anda harapkan? Pada gambar terlampir saya hanya melihat semesta simbol dan warna.
mgri
1
Contoh data akan membantu di sini. Apakah Anda memiliki satu fitur per lampu sektor, atau satu fitur per pelampung? Plugin Wedge Buffer mungkin membantu di sini, tetapi betapa mudahnya ini akan tergantung pada bagaimana data Anda diatur.
Steven Kay
Hai @ gri dan Steven, saya menambahkan contoh data dan mencoba membuat pertanyaan menjadi lebih jelas :), terima kasih!
Benjamin Donner
1
@mgri garis-garisnya bukan variabel, tetapi garis yang seharusnya ditampilkan secara statis sebagai garis panjang 900m antara sektor-sektor ringan seperti pada gambar. Sistem referensi yang diproyeksikan.
Benjamin Donner

Jawaban:

50

EDIT Saya mengedit jawaban untuk mengelola situasi tertentu (karena nilai sudut tertentu) dan untuk tidak menampilkan garis putus-putus ketika sudut bundar ditentukan.


Saya mengusulkan solusi dengan hanya berulang pada simbologi dan pelabelan berbasis aturan.

Sebelum memulai, saya ingin menggarisbawahi bahwa saya akan memusatkan perhatian pada penjelasan tentang hal-hal minimal yang harus dilakukan untuk mereproduksi hasil yang diinginkan: ini berarti bahwa beberapa parameter kecil lainnya (seperti ukuran, lebar dan sebagainya) harus mudah disesuaikan oleh Anda untuk lebih menyesuaikan kebutuhan Anda.

Selain itu, solusi ini hanya berfungsi jika Anda menganggap bahwa 0derajat adalah Utara dan bukan Selatan (jika 0Selatan, sebaliknya, itu akan cukup menjumlahkan suatu180 nilai setiap kali muncul '90' dalam rumus yang berhubungan dengan sudut, misalnya cos(radians(90))akan menjadi cos(radians(180 + 90))). Saya lebih suka melakukan ini hanya demi memberikan solusi yang lebih umum.


Styling

Kami akan memberikan poin dengan a Single symboldan dengan berulang ke satu Simple Markerdan tiga Geometry generatorlapisan simbol:

masukkan deskripsi gambar di sini

Dalam penjelasan lebih lanjut, saya akan mengikuti urutan simbol yang sama pada gambar di atas.

1) Penanda Sederhana

Saya memilih simbol default bintang hitam (ini adalah bagian yang lebih mudah dari tutorial ini), memiliki ukuran 3 mm dan lebar 0,4 mm.

2) Generator Geometri No. 1

Tambahkan layer simbol baru dan pilih Geometry generatorjenisnya:

masukkan deskripsi gambar di sini

Masukkan ungkapan ini di Expressionbidang:

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

Kami baru saja mendefinisikan garis pertama yang menunjuk ke titik di mana sektor cahaya dimulai. Garis ini panjangnya 1000 m dan dibuat hanya jika sudut pembukaan lampu sektor bukan sudut bundar (ini terjadi untuk menghindari bahwa garis akan memecah seluruh lingkaran).

3) Generator Geometri No. 2

Sama seperti di atas tetapi, pada langkah ini, Anda perlu menggunakan ungkapan ini:

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

Kami baru saja mendefinisikan garis pertama yang menunjuk ke titik di mana sektor ringan berakhir. Garis ini panjangnya 1000 m dan dibuat hanya jika sudut pembukaan lampu sektor bukan sudut bundar (ini terjadi untuk menghindari bahwa garis akan memecah seluruh lingkaran).

4) Generator Geometri No. 3

Masukkan ungkapan ini di Expressionbidang:

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

Kami baru saja mendefinisikan busur antara titik awal dan akhir dari sektor ringan (harap dicatat bahwa 2000ini adalah nilai arbitrer karena saya mencoba membuat poligon untuk memotong dengan batas lingkaran yang memiliki jari-jari 900 m).

Selanjutnya, kita perlu mengatur warna yang disimpan di "VARIS"lapangan. Untuk melakukan ini, kita perlu menentukannya dengan ekspresi khusus. Ikuti panah pada gambar di bawah ini:

masukkan deskripsi gambar di sini

dan kemudian ketik ungkapan ini setelah mengklik Edit...tombol:

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

Harap perhatikan bahwa, untuk lapisan simbol ini, saya membuat dua baris: garis atas menentukan warna yang akan digunakan (sebenarnya saya mengatur ekspresi khusus untuk yang satu ini), sedangkan yang lebih rendah berguna untuk menentukan batas hitam (akan memiliki lebar yang lebih besar dari pada garis atas). Ingat juga untuk mengatur Flatsebagai Cap styleuntuk kedua baris untuk menghindari warna yang tumpang tindih.


Pelabelan

1) Mengatur label

Pergi ke Layer Properties> Labelsdan, seperti biasa, ikuti panah merah:

masukkan deskripsi gambar di sini

lalu ketikkan ungkapan ini:

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

Kami baru saja menetapkan aturan warna menggunakan nilai yang disimpan di "VARIS"bidang.

2) Mengatur penempatan untuk label

Pilih Placementopsi di LabelsMenu dan pilih Offset from point.

Kemudian, dengan mengacu pada gambar di bawah ini:

masukkan deskripsi gambar di sini

ikuti panah merah dan ketik ungkapan ini:

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

Kemudian, ikuti panah hijau dan ketikkan ungkapan ini:

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

Hasil akhir

Jika Anda melakukan tugas-tugas sebelumnya dengan benar, Anda seharusnya bisa mendapatkan hasil ini:

masukkan deskripsi gambar di sini

Bonus

Karena parameter minor terlalu banyak untuk sepenuhnya tercakup dalam jawaban ini, saya telah melampirkan gaya di sini : Anda dapat membuka kode ini dengan editor teks apa pun dan menyimpannya sebagai file QGIS Layer Style (yaitu dengan .qmlekstensi).

Gaya di atas dibuat menggunakan QGIS 2.18.4 (harus memiliki nama yang sama dengan shapefile yang Anda gunakan).

mgri
sumber
3
Tampak hebat, benar-benar menunjukkan kekuatan generator geometri. Apakah lambat untuk membuat?
HeikkiVesanto
2
@ Vesanto Saya mengujinya pada satu titik yang memiliki enam fitur (yaitu enam lampu sektor) dan ditampilkan secara instan. Saya pikir itu harus cepat juga ketika berhadapan dengan ratusan fitur karena tidak ada panggilan ke penyedia atau sesuatu yang serupa, tetapi hanya beberapa operasi matematika dan geometri sebagai Well Know Text.
mgri
2
Pertanyaan / jawaban seperti ini benar-benar menunjukkan betapa serbagunanya QGIS!
Joseph
1
@mgri kamu adalah Master, solusi yang luar biasa bagus dan penjelasan hebat yang melibatkan banyak pekerjaan, TERIMA KASIH !!
Benjamin Donner
1
@MGRI gunung di wilayah ini harus diberi nama setelah kamu, terima kasih !! Saya telah menguji sedikit dan tidak ada masalah dengan solusi tambahan Anda telah ditemukan :)!
Benjamin Donner