当前位置:   article > 正文

Python地理空间分析指南(第2版)学习笔记分享——1.0第一章Python与地理空间分析

python地理空间分析指南

        简介:本文以Python地理空间分析指南(第2版)第一章为基本,对于书中出现的概念只是简要的说明,大家如果不懂可以自行补充,此文主要以程序分析为基本,用到的python版本为3.9。此节对于程序SimpleGIS为重点,进行了全面的刨析,以及所需要的turtle库进行的简单讲解。

基本概念

        本书第一章介绍了GIS与遥感方面基本概念,如地信与遥感的概念、矢量数据栅格数据的介绍,对于地信人员来说是基础。如果你还不是对地信与遥感这方面特别熟练,推荐着重学习一些相关软件如Arcgis与ENVI,实践学习相结合更好的帮助自己理解并学习掌握这方面内容,为接下来学习做准备。

SimpleGIS所涉及的库

        对于简单的Python没有太多概述,建议大家可以自学,能够使用列表、字典、类、函数即可;本章设计的库为turtle库,用到的代码如下:

turtle.up()——抬起画笔(在移动过程中不会画线)

turtle.down()——画笔落下(将抬起的画笔放下,使能在屏幕绘制线条)

turtle.goto(x,y)——移动画笔至(x,y)点

turtle.write()——写入文本

turtle.dot()——画点(在屏幕上标记出点)

turtle.done()——持续打开图画

turtle.pen(shown=False)——隐藏光标

其他turtle库以及各种参数请参考turtle --- 海龟绘图 — Python 3.10.8 文档

SimpleGIS解析 

导入turtle,并赋值变量。

  1. import turtle as t
  2. NAME=0
  3. POINTS=1
  4. POP=2


建立一个包含科罗拉多州城市、坐标、人口的列表。

state=["科多里达",[[-109,37],[-109,41],[-102,41],[-102,37]],5187582]


创建一个城市空列表,将3个城市信息(包含名字、坐标、人口)分别建立三个列表并添加到城市列表中。

  1. cities=[]
  2. cities.append(['DENVER',[-104.98,39.71],634265])
  3. cities.append(['BOULDER',[-105.27,40.02],98889])
  4. cities.append(['DURANGO',[-107.88,37.28],17069])


采用赋值变量的形式定义地图尺寸。

  1. map_width=400
  2. map_height=300


确保州尺寸在地图中,如果不在将自动调整。

  1. 这里最大/小x,y代表的为经纬度(以°为单位),东西经各180°则分为±180°,南北纬同理。我们定义到xy的最大最小值范围。
  2. 使用for循环,前面我们定义过POINTS=1,这里索引state[POINTS]表示索引state列表第二个值第二个值为四个点组成的列表,即[[-109,37],[-109,41],[-102,41],[-102,37]]。从这里x,y将继续索引四个点组成的列表,首先索引[-109,37]其次[-109,41]直至索引到最后,第一次索引时会给x赋值为-109,y赋值为37,之后的索引的类似。
  3. 我们要确保的周边界并不是地球的边界,所以采用if条件语句改变minx/miny/maxx/maxy的边界为州边界。
  1. minx=180
  2. maxx=-180
  3. miny=90
  4. maxy=-90
  5. for x,y in state[POINTS]:
  6.     if x<minx:
  7.         minx=x
  8.     elif x>maxx:
  9.         maxx=x
  10.     if y <miny:
  11.         miny=y
  12.     elif y>maxy:
  13.         maxy=y


计算州和绘图版的缩放比例

  1. 要将地图显示到州的范围,此外我们输入的数据是经纬度坐标,而屏幕显示的是400*300的画布,需要进行经纬度与画布的宽高(400*300)的转化。
  2. 求x,y(经纬度坐标)在的总长得到dist_x与dist_y。例:maxx=-102°,minx=-107°因此总长应为dist_x=-102°-(-107°)=5°
  3. 分别计算经纬度1°等于画布的长度为多少。例:上例中的总长为5°我们用画布的宽400做计算x_ratio=map_width/dist_x=400/5=80。
  1. dist_x=maxx-minx
  2. dist_y=maxy-miny
  3. x_ratio=map_width/dist_x
  4. y_ratio=map_height/dist_y

定义convert函数,使用缩放比例将经纬度转换为平面坐标,类似于转换投影坐标系。

  1. 这里的定义函数前三行代表意思的为定义一个函数,这个函数形参为一个列表,前两个值应该为lon和lat即经纬度。
  2. 3、4行则表示转化过来的点x、y应该在画布的什么位置(从经纬度转化到画布上位置)。maxx-lon表示经度为在州的范围内所处的位置(锁定州的范围后,坐标系不是从0开始的而且从minx开始的)。例:假设州的范围为-107~-102°E,27°~39°N,输入点坐标为(-105,30),以经度为例maxx-lon=-102-(-105)=3°,所得结果为点值州最大边界的距离。即-105至-102的距离。
  3. 得到输入点至边界的最大距离后将其*x_ratio表示将经纬度距离转到画布距离。以上文为例:3°*80=240,即输入点到画布最大值边界距离为240
  4. 用map_width-点到画布最大值边界距离即可获得输入点在画布的x坐标。例:400-240=160此时该点在画布的x坐标为160。同理获得y坐标。
  5. 5、6行表示移动到中心位置,画布开始位置(0,0)点位于边界的左下角,要调整(0,0)点为画布中心。
  1. def convert(point):
  2.     lon=point[0]
  3.     lat=point[1]
  4.     x=map_width-((maxx-lon)*x_ratio)
  5.     y=map_height-((maxy-lat)*y_ratio)
  6.     x=x-(map_width/2)
  7.     y=y-(map_height/2)
  8.     return [x,y]

 
打印州的区域

  1. state[POINTS]代表州的四个点坐标组成的列表,用for循环遍历这个列表。每次循环获得一个点坐标point。
  2. 在一次循环中调用convert函数让pixel为转换后的坐标,并用if条件语句判断第一个点,以便闭合(下面的t.goto()在闭合时需要第一个点的位置),转换后使用t.goto()定位到该点,并用t.down()使画笔落下,移动时进行画线。将循环执行完。
  3. 这里的if语句,开始定义了一个first_pixel=None,让first_pixel为空,if not first_pixel表示如果first_pixel没有值时将执行...。在这里第一次循环获得第一个点后,第二次循环first_pixel将有值if语句将不再执行。
  4. 循环结束后,继续定位到第一个点first_pixel并用t.up()抬起画笔不再画线。
  5. 定位到(0,0)画布中心,使用t.write()书写州的各种信息。
  1. t.up()
  2. first_pixel=None
  3. for point in state[POINTS]:
  4.     pixel=convert(point)
  5.     if not first_pixel:
  6.         first_pixel=pixel
  7.     t.goto(pixel)
  8.     t.down()
  9. t.goto(first_pixel)
  10. t.up()
  11. t.goto([0,0])
  12. t.write(state[NAME],align='center',font=('Arial',16,'bold'))


绘制城市各个城市

  1. for city in cities:
  2.     pixel=convert(city[POINTS])
  3.     t.up()
  4.     t.goto(pixel)


  绘制城市位置

    t.dot(10,'red')


标记城市

  1.     t.write(f'城市:{city[NAME]}人口:{city[POP]}',align='left')
  2.     t.up()


查询人口最多的城市

  1. biggest_city=max(cities,key=lambda city:city[POP])
  2. t.goto(0,-200)
  3. t.write(f'人口最多的城市是{biggest_city[NAME]}')


查询离西部最远的城市

  1. western_city=min(cities,key=lambda city:city[POINTS])
  2. t.goto(0,-220)
  3. t.write(f'最靠近西的为{western_city[NAME]}')


隐藏光标并持续打开
 

  1. t.pen(shown=False)
  2. t.done()

原码

'''导入turtle'''
import turtle as t
NAME=0
POINTS=1
POP=2
'''一个包含科罗拉多州城市、坐标、人口的列表'''
state=["科多里达",[[-109,37],[-109,41],[-102,41],[-102,37]],5187582]
'''城市信息'''
cities=[]
cities.append(['DENVER',[-104.98,39.71],634265])
cities.append(['BOULDER',[-105.27,40.02],98889])
cities.append(['DURANGO',[-107.88,37.28],17069])
'''定义地图尺寸'''
map_width=400
map_height=300
'''确保州尺寸在地图中,如果不在自动调整'''
minx=180
maxx=-180
miny=90
maxy=-90
for x,y in state[POINTS]:
    if x<minx:
        minx=x
    elif x>maxx:
        maxx=x
    if y <miny:
        miny=y
    elif y>maxy:
        maxy=y
'''计算州和绘图版的缩放比例'''
dist_x=maxx-minx
dist_y=maxy-miny
x_ratio=map_width/dist_x
y_ratio=map_height/dist_y
'''convert函数,使用缩放比例将经纬度转换为XY坐标'''
def convert(point):
    lon=point[0]
    lat=point[1]
    x=map_width-((maxx-lon)*x_ratio)
    y=map_height-((maxy-lat)*y_ratio)
    x=x-(map_width/2)
    y=y-(map_height/2)
    return [x,y]
'''打印区域'''
t.up()
first_pixel=None
for point in state[POINTS]:
    pixel=convert(point)
    if not first_pixel:
        first_pixel=pixel
    t.goto(pixel)
    t.down()
t.goto(first_pixel)
t.up()
t.goto([0,0])
t.write(state[NAME],align='center',font=('Arial',16,'bold'))
'''绘制城市'''
for city in cities:
    pixel=convert(city[POINTS])
    t.up()
    t.goto(pixel)
    # 绘制城市位置
    t.dot(10,'red')
    # 标记城市
    t.write(f'城市:{city[NAME]}人口:{city[POP]}',align='left')
    t.up()
# 查询人口最多
biggest_city=max(cities,key=lambda city:city[POP])
t.goto(0,-200)
t.write(f'人口最多的城市是{biggest_city[NAME]}')
# 哪个离西部最远
western_city=min(cities,key=lambda city:city[POINTS])
t.goto(0,-220)
t.write(f'最靠近西的为{western_city[NAME]}')
# 隐藏光标并持续打开
t.pen(shown=False)
t.done()

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/883300
推荐阅读
相关标签
  

闽ICP备14008679号