我将lightector数据作为字段,在shapefile中提供becon_id,开始程度,结束程度和颜色,其中需要在地图上显示500多个浮标,信标和灯塔。对于每个信标,可以有很多行,每个行描述一个光扇区(例如白色扇区)
最终结果应如下所示:正确颜色的光扇区,颜色在色域(RGW)中标记为字符,并从浮标/信标/灯塔到100m至1000m的虚线。
很可能应该将其创建为基于规则的符号,但是我猜需要一些python吗?
以下是一个灯塔的shapefile数据示例,该灯塔的绿色扇区在114到154度之间,白色扇区在白色和白色之间在154至168度之间,红色在168至237度之间,绿色在237至314度之间,白色在314至320度之间,红色在320至337度之间(由于某些原因,0不是北但南部):
#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
评论
相关的gis.stackexchange.com/questions/170950/…请,您可以上传样本数据集并通过详细说明您期望的结果来编辑问题吗?在所附的图像中,我仅看到符号和颜色的范围。
示例数据将在这里有所帮助。每个扇形灯有一个功能,还是每个浮标有一个功能? Wedge Buffer插件在这里可能会有所帮助,但这是否简单取决于您的数据设置方式。
@mgri和Steven,您好,我添加了示例数据并试图使问题更清晰:),谢谢!
@mgri线不是变量,而是应静态显示为光扇之间的900m长线(如图像中所示)。投影参考系统。