分享

地图制作 何必什么都用 gis 软件完成,以“风玫瑰图”为例!

 GIS荟 2021-09-19

前言:制作地图不一定非要死磕 ArcGIS,不仅可以使用 QGIS,甚至可以直接使用 ps,更专业更精细化一点甚至可以使用 Adobe Illustrator,当然也可以使用 Python 啦,这里用一个简单的例子来抛砖引玉。

风玫瑰图

这一段时间我看到有人在求助如何使用 ArcGIS 添加风玫瑰图,还重复看到了好几次,然后我自己去试了试,发现使用 ArcGIS 确实不太好弄。

1.什么是风玫瑰图

风玫瑰图(wind rose plot)用来简单描述某一地区风向风速的分布,可分为风向玫瑰图和风速玫瑰图。在风玫瑰图的极坐标系上,每一部分的长度表示该风向出现的频率,最长的部分表示该风向出现的频率最高。风玫瑰图通常分16个方向,也有的再细分为32个方向。

风玫瑰图可以直接替代指北针,所以有的人也叫玫瑰指北针,为什么名字里都有一个“玫瑰”呢?可能是形状像玫瑰花瓣吧。

两个简单的风玫瑰图;

2.添加方法

ArcGIS 没有自带的风玫瑰图,并且 ArcGIS 不支持 svg 格式,支持一种叫 emf (好像叫这个)的远古狗屎格式,在我的测试下非常难用。

所以要如何才能把风玫瑰图添加到地图中呢?

有发现一些有趣的解决办法:直接把风玫瑰图拖进 arcmap 中(不能是 png 格式的),然后可以重分类,再配准到地图上。这个方法不错,大家可以尝试,不过这个很可能出现各种范围报错。

其实为什么非得要使用 ArcGIS 做呢?直接使用 PS 把风玫瑰图加上去就行了。

或者更快速更有效,直接使用 python 的 PIL 库也可以实现把风玫瑰图加到地图的指定位置,甚至可以批量添加。

使用Python添加风玫瑰图

1.数据资料准备

1.1制作完成的地图

基本制作完成的地图或多张(不包含指北针,因为风玫瑰图就能替代指北针)。

map.jpg

1.2风玫瑰图

准备已经制作好的风玫瑰图,最好使用 svg 格式,这个格式是一种广泛用于网络的矢量格式,是万维网的标准,也是制作各种图标的标准格式之一;或者使用 png 格式也可以,但要保证大小分辨率足够,不然最后添加到地图上会模糊。

作者使用的风玫瑰图 wind-rose.png

符号来源:https://www./png-zuwuu1/

2.添加风玫瑰图

2.1导入 PIL 模块

现在在 Python3 中安装 PIL 模块实际上是指 Pillow 模块,因为原来的 PIL 模块已经不更新了,而 Pillow 模块是对 PIL 的继承和发展。同时 Pillow 模块完全继承了 PIL 的所有语法和各种名词空间,包括导入方式。

from PIL import Image

2.2获取图片尺寸

获取地图的尺寸和风玫瑰图的尺寸。

# Get map size
#   map_x: map image X
#   map_x: map image Y
map_path = "map.jpg"
we_map = Image.open(map_path)
map_x = we_map.size[0] # 宽
map_y = we_map.size[1] # 高
# 风玫瑰图与边框的距离
offset_x , offset_y = 420, 420 # ▶注释1◀

# Get windrose image size:
#   w_d_x: windrose image X
#   w_d_y: windrose image Y
windrose_path = "wind-rose.png"
windrose = Image.open(windrose_path)
print(windrose.size)
w_d_x = windrose.size[0]
w_d_y = windrose.size[1]

获取的图片尺寸是一个 宽 高 组成的元组:(width, height)。

▶注释1◀:

①这里的 offset_x 和 offset_y 指风玫瑰图(下图中的黑色矩形)到边框的距离,亮橙色箭头。

②图像中的坐标系和一般的数学坐标系是不一样的,坐标原点在图像左上端点,Y 轴向下为正,X 轴向左为正。

2.3粘贴区

将风玫瑰图粘贴到地图前,需要在地图上预先设置一个“粘贴区”,且尺寸大小需要和风玫瑰图大小保持一致。

x_topleft = map_x - offset_x - w_d_x
y_topleft = offset_y
x_bottomright = map_x - offset_x
y_bottomright = offset_y + w_d_y
box=(x_topleft, y_topleft, x_bottomright, y_bottomright)

这个 box 就是所谓的“粘贴区”,其中依次输入左上角x坐标左上角y坐标右下角x坐标右下角y坐标

2.4粘贴

最后一步就是把风玫瑰图粘贴到地图上,然后 save 保存。

# 使用透明图层为掩膜裁剪出目标区域。
clip_mask = windrose.convert('RGBA')
we_map.paste(windrose, box, clip_mask)
we_map.save("test.jpg")

需要注意的一点就是腌膜,腌膜可以帮助将 png 图片中的透明部分裁剪扔掉。

未使用腌膜

使用腌膜

3.完整代码和成果

# -*- coding:utf-8 -*-

from PIL import Image

# Get map size
#   map_x: map image X
#   map_x: map image Y
map_path = "map.jpg"
we_map = Image.open(map_path)
map_x = we_map.size[0]
map_y = we_map.size[1]
# 风玫瑰图与边框的距离
offset_x , offset_y = 420, 420

# Get windrose image size:
#   w_d_x: windrose image X
#   w_d_y: windrose image Y
windrose_path = "wind-rose.png"
windrose = Image.open(windrose_path)
print(windrose.size)
w_d_x = windrose.size[0]
w_d_y = windrose.size[1]


x_topleft = map_x - offset_x - w_d_x
y_topleft = offset_y
x_bottomright = map_x - offset_x
y_bottomright = offset_y + w_d_y
box=(x_topleft, y_topleft, x_bottomright, y_bottomright)


# 使用透明图层为掩膜裁剪出目标区域。
clip_mask = windrose.convert('RGBA')
we_map.paste(windrose, box, clip_mask)
we_map.save("test.jpg")
# we_map.show()

最后

代码量很少,这里只是展示一个思路,抛砖引玉,毕竟还有使用 PS 这种更加简单快速的方法。

最后的成果图

荟GIS精粹,关注公众号:GIS荟

欢迎交流,更多文章请使用搜索

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多