如果第一个标签不适合QGIS,请更改为备用标签?


10

我正在尝试创建要打印的地图,并且多边形的大小差异很大。由于这将是参考地图,因此我需要标记每个多边形,但是某些名称将不适合该多边形。在这些情况下,我想改用功能ID,然后让属性表将ID链接到名称。

我想做的是具有某种表达式,可以用来选择在地图上使用的标签以及在属性表中包括的行。这样的isLabelled事情将能够考虑地图比例,标签长度,字体大小等。


2
请记住,如果以不同的方式标记相同要素类的多边形,并且另外只有一部分出现在属性表中,这可能会使地图用户感到困惑。
tallistroan

我正在考虑GB的县级地图
伊恩·特顿

如何动态更改字体以适合呢?您可以采用最长的特征尺寸,除以标签字符串中的字符数,然后对比例进行一些数学运算,或者仅使用它来更改已设置的字体大小。或者,可以使用该度量(最长特征尺寸/字符串的len),以及如果标签的ID过长。
杰西·麦克米兰

我主要是在意可读性,所以我不想弄乱字体的大小
伊恩·图顿

1
您可以使用Python自定义表达式来获取标签,字体大小和比例,并在合适的情况下返回true或false。然后在表达式引擎中使用if子句来切换标签。稍后将通过示例为您解答。
杰西·麦克米兰

Answers:


8

这是一种近似(但希望有效)的方法。

首先一些数学。我们需要找出某个功能可以包含多少个特定字体大小的字符。这里的事情/假设要知道:

  • 假设为公制单位((在此基础上再加上一些细微变化,这可能会使我们的脚用脚单位)。
  • 字体大小是字体高度的度量。大多数字体的宽度大约是高度的一半。
  • 使用pt作为字体高度,大约1pt约为0.035CM
  • 假设您的包裹大致是矩形/规则的

要查找一个项目在屏幕上/打印上的时间,我们可以使用它的最长尺寸(长度或高度,或者如果标签仅水平,则为长度)/比例* 100(从M到CM)

然后,我们可以查看标签是否适合。

您可以在表达式引擎中完成所有操作,但是自定义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('composername','mapname'),以便将其合并到我们的表达式中:

if(
    labelFits( "yourAttribute" , 8 , getScale('composername','mapname')),
    "yourAttribute",$id)

1
我也在想类似的事情。特别是如果使用地图单位和以米为单位的投影。假设标签位于质心的中心,新的(ish)几何运算符也可以在此处提供帮助。使用固定宽度(等距)字体比比例字体(例如,“ W”比“ i”宽得多)会更好。您正在这里进行一些操作,但是我怀疑比例字体和字距调整会增加复杂性。
史蒂文·凯

您可以使用pil的imagefont.getsize()。这将为您提供以您选择的字体呈现的字符串的确切宽度,但是我认为这会对性能产生重大影响。上面的粗略数学要简单得多,尤其是如果您在屏幕上有数百个标签时
Jesse McMillan

唯一的小问题是,该函数似乎无法在print composer的属性表中用作过滤器。
伊恩·特顿

您的地图比例因页面而异吗?尝试手动输入比例尺而不是@map_scale变量。我的猜测是属性表无法知道您的地图比例。(例如,因为您可能在作曲家中使用不同比例的多个地图项)
Jesse McMillan

1
@iant我张贴了指向另一个自定义表达式的链接,该链接将以编程方式获取您的作曲家地图的比例。
杰西·麦克米兰

3

复制该图层(没有符号系统的图层),并为每个标签设置不同的缩放级别/障碍设置。


1

我有类似的情况,有义务标记道路图层中的每条道路。我的解决方案是创建更大尺寸的画布,导出为PDF,然后将PDF打印为所需大小。

例如,要求成品为A3。在A3的画布上,我无法容纳所有标签。因此,我制作了画布A2,并且可以看到所有标签。创建A2尺寸图的PDF并将其打印为A3。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.