Mengubah ke label alternatif jika label pertama tidak cocok dengan QGIS?

10

Saya mencoba membuat peta untuk dicetak dan ukuran poligon saya sangat bervariasi. Karena ini akan menjadi peta referensi saya perlu memberi label setiap poligon, tetapi beberapa nama tidak akan cocok dengan poligon. Dalam kasus itu, saya ingin menggunakan id fitur dan kemudian memiliki tabel atribut yang menghubungkan id ke nama.

Yang ingin saya lakukan adalah memiliki semacam ekspresi yang dapat saya gunakan untuk memilih label mana yang akan digunakan pada peta dan baris mana yang akan dimasukkan dalam tabel atribut. Sesuatu seperti isLabelleditu akan dapat memperhitungkan skala peta, panjang label, ukuran font, dll.

Ian Turton
sumber
2
Perlu diingat, bahwa itu mungkin membingungkan bagi pengguna peta, ketika poligon dari kelas fitur yang sama diberi label dengan cara yang berbeda dan selain itu hanya beberapa dari mereka yang muncul dalam tabel atribut.
tallistroan
Saya sedang memikirkan peta wilayah GB
Ian Turton
Bagaimana dengan perubahan font secara dinamis agar sesuai? Anda dapat mengambil dimensi fitur terpanjang, dibagi dengan berapa banyak karakter dalam string label, dan melakukan beberapa matematika dengan skala atau hanya menggunakannya untuk mengubah ukuran font yang sudah Anda tetapkan ... Atau Anda dapat menggunakan ukuran itu (terpanjang) dimensi fitur / len string) dan jika terlalu panjang label dengan id.
Jesse McMillan
sebagian besar saya khawatir dengan keterbacaan jadi saya tidak ingin mengacaukan ukuran font
Ian Turton
1
Anda bisa menggunakan ekspresi kustom Python mengambil label, ukuran font, dan skala dan mengembalikan benar atau salah jika cocok. Kemudian dalam mesin ekspresi gunakan klausa if untuk mengganti label. Saya akan mengerjakan jawaban untuk Anda nanti dengan contoh.
Jesse McMillan

Jawaban:

8

Inilah cara yang agak mendekati (tapi mudah-mudahan efektif) untuk melakukannya.

Pertama beberapa matematika. Kita perlu mencari tahu berapa banyak karakter pada ukuran font tertentu yang dapat berisi fitur. Berikut hal-hal / asumsi yang perlu diketahui:

  • dengan asumsi satuan metrik, (menambahkan sedikit perubahan di bawah ini yang mungkin membuat ini berhasil bagi kami, kaki)
  • ukuran font adalah ukuran ketinggian font. Sebagian besar font sekitar setengah lebarnya.
  • menggunakan pt untuk ketinggian font, 1pt adalah 0,035CM
  • dengan asumsi paket Anda kira-kira persegi panjang / reguler

Untuk mengetahui berapa lama suatu item ada di layar / cetak, kita dapat menggunakannya dengan dimensi terpanjang (panjang atau tinggi, atau hanya panjang jika label Anda hanya horisontal) / skala * 100 (untuk beralih dari M ke CM)

Lalu kita bisa melihat apakah label kita cocok.

Anda bisa melakukan semuanya di mesin ekspresi, tetapi ekspresi python khusus akan lebih efisien. Berikut ini tutorial tentang cara membuatnya.

Ekspresi khusus saya:

from qgis.core import *
from qgis.gui import *

@qgsfunction(args='auto', group='Custom')
def labelFits(labelStr, fontPt, scaleM, feature, parent):
    # returns true if a label will fit in the feature at a given
    # font size and scale

    bbox = feature.geometry().boundingBox()

    # for CRS in us foot
    # fontWidth = fontPt * 0.0875

    # for CRS in metric
    # 1pt = 0.035CM
    fontWidth = fontPt * 0.035 * 0.5

    # length of maximum dimension on-screen/print in CM
    labelRoom =  max(bbox.width(),bbox.height()) / scaleM * 100

    # approx length of our label in CM based on font height * 0.5
    labelLen = len(labelStr) * fontWidth

    if labelRoom > labelLen:
        return True
    else:
        return False

Kemudian gunakan saja ungkapan itu di label:

if(labelFits( "yourAttribute" , 8 , @map_scale ), "yourAttribute",$id)

Anda harus memasukkan atribut apa pun yang sebenarnya Anda gunakan, dan mengubah ukuran font dari 8 menjadi apa pun yang Anda gunakan. Juga, karena font sedikit berbeda, Anda mungkin perlu mengubah sedikit sampai terlihat benar.

Anda juga bisa menggunakan ungkapan itu untuk melakukan hal-hal seperti mengubah warna berdasarkan apakah labelnya cocok atau tidak.


Untuk menggunakan ungkapan ini di luar kanvas peta (yaitu dalam label komposer atau tabel atribut) kita perlu cara untuk secara programatik mendapatkan skala dari item peta yang diberikan. Saya telah memposting kode untuk menyelesaikannya di jawaban lain di sini . Metode di sana memberi kami ekspresi getScale ('composername', 'mapname') sehingga untuk memasukkannya ke dalam ekspresi kami:

if(
    labelFits( "yourAttribute" , 8 , getScale('composername','mapname')),
    "yourAttribute",$id)
Jesse McMillan
sumber
1
Saya juga memikirkan sesuatu yang serupa. Terutama jika menggunakan unit peta dan proyeksi dalam meter. Operator geometri (ish) baru juga dapat membantu di sini, dengan asumsi label dipusatkan pada centroid. Ini akan bekerja lebih baik dengan font dengan lebar tetap (monospasi) daripada font proporsional (di mana 'W' jauh lebih luas daripada 'i', misalnya). Anda menemukan sesuatu di sini, tetapi saya curiga font proporsional dan kerning akan menambah kerumitan.
Steven Kay
Anda dapat menggunakan pil's imagefont.getsize (). Itu akan memberi Anda lebar yang tepat dari string yang diberikan dalam font yang Anda pilih, tapi saya pikir itu akan memiliki hit kinerja utama. Matematika kasar di atas jauh lebih sederhana, terutama jika Anda memiliki ratusan label di layar
Jesse McMillan
Satu-satunya masalah kecil adalah bahwa fungsi tersebut tampaknya tidak berfungsi sebagai filter dalam tabel atribut dalam komposer cetak.
Ian Turton
Apakah skala peta Anda bervariasi dari halaman ke halaman? Coba masukkan skala secara manual alih-alih variabel @map_scale. tebakan saya adalah tabel atribut tidak memiliki cara untuk mengetahui skala peta Anda. (Karena misalnya Anda dapat memiliki beberapa item peta dalam komposer pada skala yang berbeda)
Jesse McMillan
1
@iant Saya memposting tautan ke ekspresi kustom lain yang akan mendapatkan skala peta komposer Anda secara terprogram.
Jesse McMillan
3

Gandakan layer, satu tanpa simbologi, dan atur tingkat pembesaran / pengaturan hambatan yang berbeda untuk masing-masing label.

Tom Chadwin
sumber
1

Saya memiliki situasi yang serupa dengan kewajiban untuk memberi label pada setiap jalan di lapisan jalan. Solusi saya adalah membuat kanvas dengan ukuran yang lebih besar, mengekspor ke PDF dan kemudian mencetak PDF ke ukuran yang diperlukan.

Misalnya, produk jadi harus A3. Di atas kanvas di A3 saya tidak bisa memuat semua label. Jadi saya membuat kanvas A2 dan memungkinkan semua label terlihat. Buat PDF dari peta ukuran A2 dan cetak sebagai A3.

Johanna
sumber