Kontrolujesz etykietowanie oparte na regułach za pomocą PyQGIS?

15

Kontynuując to pytanie: Jak włączyć / wyłączyć wszystkie etykiety wszystkich warstw w QGIS , OP wspomniał w swoim komentarzu , że używa etykiet opartych na regułach. Próbowałem wyszukać w Internecie, jak można czytać i modyfikować tego rodzaju etykiety, ale udało mi się znaleźć ten post z lutraconsulting :

Aby ułatwić dodawanie etykiet opartych na regułach, wprowadzono pewne wewnętrzne zmiany w interfejsie silnika etykietowania QGIS. Etykietowanie jest teraz kierowane przez nową klasę, z QgsLabelingEngineV2którą może być powiązanych kilku dostawców etykiet.

Brzmi wspaniale. Jednak podczas czytania klasy QgsLabelingEngineV2 wspomina:

ta klasa nie jest jeszcze częścią publicznego API.

Czy obecnie można kontrolować etykietowanie oparte na regułach za pomocą Pythona?

Joseph
źródło
1
Znalazłem tutaj otwarty problem dotyczący projektu dokumentacji Qgis w Github, który również o tym wspomina . Nie mogłem znaleźć powiązania SIP dla tej klasy w gałęziach MASTER lub 2.18, więc podejrzewam, że nadal jest dostępny tylko dla kodu C ++.
Steven Kay
@StevenKay - Świetne znalezisko, dzięki! Byłoby bardzo przydatne, gdyby stworzyli dla niego interfejs API ... Również dzięki za edycję, myślałem, że wkleiłem poprawny link do zajęć :)
Joseph
@StevenKay - Myślę, że teraz stworzyli API dla tego, a dokładniej klasy QgsRuleBasedLabeling :)
Joseph

Odpowiedzi:

6

Poniżej pomoc w konfiguracji od podstaw etykietowania za pomocą nowego API QGIS 3

#Configure label settings
settings = QgsPalLayerSettings()
settings.fieldName = 'myFieldName'
textFormat = QgsTextFormat()
textFormat.setSize(10)
settings.setFormat(textFormat)
#create and append a new rule
root = QgsRuleBasedLabeling.Rule(QgsPalLayerSettings())
rule = QgsRuleBasedLabeling.Rule(settings)
rule.setDescription(fieldName)
rule.setFilterExpression('myExpression')
root.appendChild(rule)
#Apply label configuration
rules = QgsRuleBasedLabeling(root)
myLayer.setLabeling(rules)
myLayer.triggerRepaint()

Niestety nie mogę znaleźć sposobu na iterację istniejących reguł, metoda labeling () dostępna dla warstw wektorowych zwraca obiekt klasy QgsAbstractVectorLayerLabeling, ale wydaje się, że nie ma sposobu na uzyskanie reguły root ( QgsRuleBasedLabeling ) z tej klasy, jedyna możliwość Odkryłem, że mogę uzyskać ustawienia PAL bezpośrednio przy użyciu identyfikatorów dostawców, ale nie mam dostępu do drzewa reguł. Czy ktoś ma jakiś pomysł?

EDYTOWAĆ

Zostało to naprawione, funkcja labeling () zwraca QgsRuleBasedLabeling (): https://github.com/qgis/QGIS/commit/4b365a8f47d96b35f7609859e580388927ae0606

domlysz
źródło
Dziękuję za odpowiedź, dobrze opracowana! Mam nadzieję, że nie masz nic przeciwko, ale nieznacznie zmodyfikowałem Twój post, aby uwzględnić myLayer.triggerRepaint()odświeżenie warstwy i zezwolenie na wyświetlanie etykiet natychmiast po ustawieniu reguł :)
Joseph
3

Z QGIS 3 dostępna jest nowa klasa QgsRuleBasedLabeling, która pozwala kontrolować etykietowanie oparte na regułach za pomocą nowego API.

Reguły można dodawać za pomocą QgsRuleBasedLabeling :: Rule .


( Niestety nie mogę w tej chwili przetestować wersji 2.99. Z radością przyjąłbym odpowiedź, gdyby stanowiła działający przykład. )

Joseph
źródło
1

Tego używam do zmiany wyrażenia filtru w opartej na regułach symbolice w QGIS 2.18, nie jestem pewien, czy o to prosisz. Dokumentacja interfejsu API na stronie http://qgis.org/api/2.18/classQgsRuleBasedRendererV2.html

import re
lddLrs = qgis.utils.iface.legendInterface().layers()    #get all loaded layers
for lyr in lddLrs:
    if (lyr.type()==QgsMapLayer.VectorLayer and lyr.name()=='layer_with_rules'): rLyr = lyr

newType = 1
for child in rLyr.rendererV2().rootRule().children():
    oldFilter = child.filterExpression()  #you can print this to see what the old expression is
    print oldFilter

    newFilter = re.sub(r"type = (\d*)", r"type = {0}".format(newType), oldFilter)  #this is an example to substitute a rule-based filter to a new number
    print newFilter

    child.setFilterExpression(newFilter)
weiji14
źródło
Dziękuję za odpowiedź, ale tak jak powiedziałeś, myślę, że dotyczy to tylko symboliki, a nie etykiet :)
Joseph