Вот несколько приблизительный (но, надеюсь, эффективный) способ сделать это.
Сначала немного математики. Нам нужно выяснить, сколько символов с определенным размером шрифта может содержать функция. Вот что нужно знать / предположения:
- предполагая метрические единицы (ниже добавлено небольшое изменение, которое может сделать эту работу для нас пешеходами)
- Размер шрифта является мерой высоты шрифта. Большинство шрифтов примерно в два раза шире, чем они высокие.
- используя pt для высоты шрифта, 1pt примерно 0.035CM
- при условии, что ваши посылки примерно прямоугольные / обычные
Чтобы определить, как долго элемент находится на экране / распечатке, мы можем использовать его самое длинное измерение (длину или высоту или просто длину, если ваши надписи только горизонтальные) / масштаб * 100 (чтобы перейти от М к СМ)
Тогда мы можем увидеть, подойдет ли наш лейбл.
Вы можете сделать все это в движке выражений, но пользовательское выражение Python будет более эффективным. Вот учебник о том, как его создать.
Мое собственное выражение:
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
Затем просто используйте это выражение в метке:
if(labelFits( "yourAttribute" , 8 , @map_scale ), "yourAttribute",$id)
Вам, конечно, нужно будет подключить любой атрибут, который вы на самом деле используете, и изменить размер шрифта с 8 на тот, который вы используете. Кроме того, поскольку шрифты сильно различаются, вам, возможно, придется немного подправить его, чтобы он выглядел правильно.
Вы также можете использовать это выражение для таких вещей, как изменение цвета в зависимости от того, подходит метка или нет.
Чтобы использовать это выражение вне холста карты (т.е. в метке композитора или в таблице атрибутов), нам нужен способ программно получить масштаб данного элемента карты. Я разместил код для выполнения этого в другом ответе здесь
. Метод там дает нам выражение getScale ('имя композитора', 'имя_карты'), чтобы включить его в наше выражение:
if(
labelFits( "yourAttribute" , 8 , getScale('composername','mapname')),
"yourAttribute",$id)