我正在使用QGIS 2.18。我需要在地图上创建用于导航的扇形灯。

我将lightector数据作为字段,在shapefile中提供becon_id,开始程度,结束程度和颜色,其中需要在地图上显示500多个浮标,信标和灯塔。对于每个信标,可以有很多行,每个行描述一个光扇区(例如白色扇区)

最终结果应如下所示:正确颜色的光扇区,颜色在色域(RGW)中标记为字符,并从浮标/信标/灯塔到100m至1000m的虚线。

很可能应该将其创建为基于规则的符号,但是我猜需要一些python吗?



以下是一个灯塔的shapefile数据示例,该灯塔的绿色扇区在114到154度之间,白色扇区在白色和白色之间在154至168度之间,红色在168至237度之间,绿色在237至314度之间,白色在314至320度之间,红色在320至337度之间(由于某些原因,0不是北但南部):



评论

相关的gis.stackexchange.com/questions/170950/…

请,您可以上传样本数据集并通过详细说明您期望的结果来编辑问题吗?在所附的图像中,我仅看到符号和颜色的范围。

示例数据将在这里有所帮助。每个扇形灯有一个功能,还是每个浮标有一个功能? Wedge Buffer插件在这里可能会有所帮助,但这是否简单取决于您的数据设置方式。

@mgri和Steven,您好,我添加了示例数据并试图使问题更清晰:),谢谢!

@mgri线不是变量,而是应静态显示为光扇之间的900m长线(如图像中所示)。投影参考系统。

#1 楼

编辑我编辑了用于管理特定情况的答案(由于特定的角度值),并且在定义圆角时不显示虚线。

我提出了一种解决方案,只重复基于规则的符号系统和标记。
在开始之前,我想强调一下,我将把注意力集中在对再现所需结果的最小操作的解释上:这意味着一些其他次要参数(例如大小,宽度等) )应该由您轻松调整以更好地满足您的需求。
此外,该解决方案仅在假设0度为北而不是南的情况下才有效(如果0为South,则将180的值相加就足够了每次在处理角度的公式中出现“ 90”时,例如cos(radians(90))将变为cos(radians(180 + 90)))。我更愿意这样做只是为了给出更通用的解决方案。

样式设置
我们将使用Single symbol渲染点,并重复出现一个Simple Marker和三个Geometry generator符号层:

在进一步的说明中,我将遵循上图中符号的相同顺序。
1)简单标记
我选择了默认符号黑星(这是
2)1号几何生成器
添加一个新的符号层并选择Geometry generator类型:

Expression字段中插入以下表达式:
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

我们刚刚定义了第一行,该行指向光扇区的起点。这条线长1000 m,并且仅在扇形灯的打开角度不是圆角时才创建(这是为了避免该线会损坏整个圆)。
3)2号几何生成器
与上述相同,但是,在此步骤中,您需要使用以下表达式:
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

我们刚刚定义了第一条线,该线指向光扇区结束的点。这条线长1000 m,并且仅在扇形灯的打开角度不是圆角时才创建(这是为了避免该线会损坏整个圆)。
4)3号几何生成器
Expression字段中插入以下表达式:
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

我们刚刚定义了光扇的起点和终点之间的弧(请注意,2000是任意值,因为我正在尝试以创建与半径为900 m的圆的边界相交的多边形。
此外,我们需要设置存储在"VARIS"字段中的颜色。为此,我们需要使用自定义表达式来指定它。遵循下图中的箭头:

,然后在单击Edit...按钮后键入以下表达式:
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

请注意,对于此符号层,我创建了两行:上一行定义要使用的颜色(实际上,我为此设置了自定义表达式),而下一行则用于定义黑色边框(其宽度大于上一行的宽度)线)。记住还要记住两行都将Flat设置为Cap style,以避免任何颜色重叠。

标签
1)设置标签
转到Layer Properties> Labels,然后照常按照红色箭头:

,然后键入此表达式:
CASE
WHEN "VARIS" = 'vi' THEN 'G'
WHEN "VARIS" = 'v' THEN 'W'
WHEN "VARIS" = 'p' THEN 'R'
END

我们刚刚使用存储在"VARIS"字段中的值定义了颜色规则。
2)设置标签的位置
Placement菜单中选择Labels选项,然后选择Offset from point
然后,参考下图:

跟随红色箭头并键入此表达式:
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

然后,跟随绿色箭头并键入以下表达式:
CASE
WHEN "ALKUKULMA" >= "LOPPUKULMA"
THEN
180-(("ALKUKULMA" + "LOPPUKULMA")/2)
WHEN "ALKUKULMA" < "LOPPUKULMA"
THEN
- (("ALKUKULMA" + "LOPPUKULMA")/2)
END

最终结果
如果您正确执行了先前的任务,则应该能够得到以下结果:

奖金
由于次要参数太多,无法完全涵盖在此答案中,因此我附上了样式:您可以使用任何文本编辑器打开此代码,并将其保存为QGIS图层样式文件(即扩展名为.qml)。
以上样式是使用QGIS 2.18.4创建的(其名称必须相同)您正在使用的shapefile)。

评论


看起来很棒,确实向您展示了几何生成器的功能。渲染速度慢吗?

– HeikkiVesanto
17年7月7日在9:21

@Vesanto我在具有六个功能(即六个扇形灯)的一点上对其进行了测试,并立即对其进行了渲染。我认为在处理数百个功能时也应该很快,因为没有调用提供程序或类似功能的要求,而只有几个数学运算和几何(如“熟知文字”)。

–mgri
17 Mar 7 '17 at 9:27

诸如此类的问题/答案确实表明了QGIS的通用性!

–约瑟夫
17 Mar 7 '17 at 10:24

@mgri,您是大师,一个了不起的好解决方案,并且涉及很多工作,谢谢您!

–本杰明·唐纳(Benjamin Donner)
17 Mar 10 '17 at 9:02

@mgri这个地区的一座山应该以你命名,谢谢!我测试了一下,没有发现您添加的解决方案有问题:)!

–本杰明·唐纳(Benjamin Donner)
17 Mar 26 '17 6:00