Python|矿产卫片Excel经纬度坐标数据转换为shp点数据——OGR库实现

1.实验需求

基于Excel表格里面的经纬度坐标数据,自动生成点shp矢量文件,并添加属性信息。

2.编程思路详解

①使用Pandas库读取原始矿产图斑列表表格;

xlsx_path = u'C:\\Users\\YaoJun\\Desktop\\矿产图斑列表.xlsx'
#sheet_name默认为0,即读取第一个sheet的数据
df = pd.read_excel(xlsx_path, sheet_name=0, index_col=0, skiprows=2)

②将中心点坐标这一列拆分为X坐标和Y坐标两列,分别去除X:/Y:多余字符;

#将中心点坐标列拆分为两列
df[[u'X坐标', u'Y坐标']] = df[u'中心点坐标'].str.split(expand=True)
#去掉X:与Y:
df[u'X坐标'] = df[u'X坐标'].map(lambda x: x.replace('X:', ''))
df[u'Y坐标'] = df[u'Y坐标'].map(lambda x: x.replace('Y:', ''))

③分别将X坐标和Y坐标两列度分秒格式转换为十进制格式;

#度分秒转换为经纬度坐标
df[u'X坐标'] = df[u'X坐标'].apply(longitude_, )
df[u'Y坐标'] = df[u'Y坐标'].apply(longitude_, )

其中,度分秒转十进制坐标的公式如下

十进制度数 = 度数 + 分数/60 + 秒数/3600。其中,度数为整数部分,分数为小数部分的整数部分,秒数为小数部分的小数部分。

例如:经度为120°30'15",则十进制度数为:120 + 30/60 + 15/3600 = 120.50416666666667

度分秒转为十进制函数如下:

#度分秒转经纬度
def longitude_(longitude):
    longitude_split = re.split(u"°|\′|\″|\'|\"", longitude)[:3]
    if len(longitude_split) == 3:
        x = [float(j) for j in longitude_split]
        data = (x[0] + x[1] / 60 + x[2] / 3600)
        return str('%.6f'% float(data))

④使用OGR库创建与Excel文件同名的点shp文件,并将表格所有列名称添加为shp字段;

 #创建输出shp文件
 shpfname = xlsx_path.split('.')[0] + ".shp"
 CreatePolygonShp(shpfname)

创建shp函数:

#创建shp文件
def CreatePolygonShp(shpfname, epsg = 4490):
    driver = ogr.GetDriverByName('ESRI Shapefile')
    if os.path.exists(shpfname):
        driver.DeleteDataSource(shpfname)
    ds = driver.CreateDataSource(shpfname)
    SpatialReference = osr.SpatialReference()
    SpatialReference.ImportFromEPSG(epsg)
    #ds.CreateLayer(shpfname, SpatialReference, geom_type=ogr.wkbPoint, options=['ENCODING=GBK'])
    ds.CreateLayer(shpfname, SpatialReference, geom_type=ogr.wkbPoint)
    del ds
    print("1.shp文件创建成功!")

创建字段函数:

#给指定shp文件添加字段函数
def AddField(shpfname, fieldname, fieldtype, fieldlenth = 50):
    ds = ogr.Open(shpfname, 1)
    layer = ds.GetLayer(0)
    # 添加字段
    fieldDefn = ogr.FieldDefn(fieldname, fieldtype)
    if fieldtype == ogr.OFTString:
        fieldDefn.SetWidth(fieldlenth)
    layer.CreateField(fieldDefn)
    del ds

将表格所有列名称添加为shp文件字段:

#添加所有列名为字段
    for col_name in df.columns[:-2]:
        if len(col_name) > 5:
            continue
        if u"面积" in col_name:
            AddField(shpfname, col_name, ogr.OFTReal)
        else:
            AddField(shpfname, col_name, ogr.OFTString, 30)

⑤遍历表格所有行,依次创建点图形并添加属性信息。

#打开空白shp
driver = ogr.GetDriverByName('ESRI Shapefile')
fc1 = driver.Open(shpfname, 1)
layer = fc1.GetLayer()
layer_defn = layer.GetLayerDefn()
field_count = layer_defn.GetFieldCount()

#添加图形与属性信息
for i in range(0, len(df.index)):
    feature = ogr.Feature(layer.GetLayerDefn())
    #依次给字段附属性值
    for j in range(field_count):
        field_defn = layer_defn.GetFieldDefn(j)
        field_name = field_defn.GetName()
        if field_name in df.columns:
            feature.SetField(field_name, str(df.iloc[i][field_name]))
    #创建点
    wkt = "POINT({} {})".format(df.iloc[i][u'X坐标'], df.iloc[i][u'Y坐标'])  # "point({} {})"两个参数之间没有逗号,记住
    point = ogr.CreateGeometryFromWkt(wkt)
    #print(point)
    feature.SetGeometry(point)
    layer.CreateFeature(feature)
    del feature

3.完整代码

# -*- coding: utf-8 -*-
# @Time    : 2023/4/16 15:49
# @Author  : 药菌

import re
import pandas as pd
from osgeo import ogr,osr,gdal
import os


gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")  # 支持文件名称及路径内的中文
gdal.SetConfigOption("SHAPE_ENCODING", "GBK")  # 支持属性字段中的中文

#度分秒转经纬度
def longitude_(longitude):
    longitude_split = re.split(u"°|\′|\″|\'|\"", longitude)[:3]
    if len(longitude_split) == 3:
        x = [float(j) for j in longitude_split]
        data = (x[0] + x[1] / 60 + x[2] / 3600)
        return str('%.6f'% float(data))

#经纬度转度分秒
def Degrees(longitude):
    data1 = int(float(longitude))
    data2 = float(float('0.'+longitude.split('.')[1])*60)
    data3 = int(data2)
    data4 = float('0.'+str(data2).split('.')[1])*60
    data5 = '%.2f'% float(data4)
    data6 = int(float(data5))
    print('度',data1)
    print('分',data3)
    print('秒',data5)
    return [data1,data3,data5]

#创建shp文件
def CreatePolygonShp(shpfname, epsg = 4490):
    driver = ogr.GetDriverByName('ESRI Shapefile')
    if os.path.exists(shpfname):
        driver.DeleteDataSource(shpfname)
    ds = driver.CreateDataSource(shpfname)
    SpatialReference = osr.SpatialReference()
    SpatialReference.ImportFromEPSG(epsg)
    #ds.CreateLayer(shpfname, SpatialReference, geom_type=ogr.wkbPoint, options=['ENCODING=GBK'])
    ds.CreateLayer(shpfname, SpatialReference, geom_type=ogr.wkbPoint)
    del ds
    print("1.shp文件创建成功!")

#给指定shp文件添加字段函数
def AddField(shpfname, fieldname, fieldtype, fieldlenth = 50):
    ds = ogr.Open(shpfname, 1)
    layer = ds.GetLayer(0)
    # 添加字段
    fieldDefn = ogr.FieldDefn(fieldname, fieldtype)
    if fieldtype == ogr.OFTString:
        fieldDefn.SetWidth(fieldlenth)
    layer.CreateField(fieldDefn)
    del ds

if __name__ == '__main__':
    xlsx_path = u'C:\\Users\\YaoJun\\Desktop\\矿产图斑列表.xlsx'
    #sheet_name默认为0,即读取第一个sheet的数据
    df = pd.read_excel(xlsx_path, sheet_name=0, index_col=0, skiprows=2)

    #将中心点坐标列拆分为两列
    df[[u'X坐标', u'Y坐标']] = df[u'中心点坐标'].str.split(expand=True)

    #去掉X:与Y:
    df[u'X坐标'] = df[u'X坐标'].map(lambda x: x.replace('X:', ''))
    df[u'Y坐标'] = df[u'Y坐标'].map(lambda x: x.replace('Y:', ''))

    #度分秒转换为经纬度坐标
    df[u'X坐标'] = df[u'X坐标'].apply(longitude_, )
    df[u'Y坐标'] = df[u'Y坐标'].apply(longitude_, )

    df.to_excel(u'C:\\Users\\YaoJun\\Desktop\\矿产图斑列表1.xlsx', index=False)

    #创建输出shp文件
    shpfname = xlsx_path.split('.')[0] + ".shp"
    CreatePolygonShp(shpfname)

    #添加所有列名为字段
    for col_name in df.columns[:-2]:
        if len(col_name) > 5:
            continue
        if u"面积" in col_name:
            AddField(shpfname, col_name, ogr.OFTReal)
        else:
            AddField(shpfname, col_name, ogr.OFTString, 30)

    #打开空白shp
    driver = ogr.GetDriverByName('ESRI Shapefile')
    fc1 = driver.Open(shpfname, 1)
    layer = fc1.GetLayer()
    layer_defn = layer.GetLayerDefn()
    field_count = layer_defn.GetFieldCount()

    #添加图形与属性信息
    for i in range(0, len(df.index)):
        feature = ogr.Feature(layer.GetLayerDefn())
        #依次给字段附属性值
        for j in range(field_count):
            field_defn = layer_defn.GetFieldDefn(j)
            field_name = field_defn.GetName()
            if field_name in df.columns:
                feature.SetField(field_name, str(df.iloc[i][field_name]))
        #创建点
        wkt = "POINT({} {})".format(df.iloc[i][u'X坐标'], df.iloc[i][u'Y坐标'])  # "point({} {})"两个参数之间没有逗号,记住
        point = ogr.CreateGeometryFromWkt(wkt)
        #print(point)
        feature.SetGeometry(point)
        layer.CreateFeature(feature)
        del feature

    pass

4.实验结果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
卫片工具包含卫星照片 显示、打印(喷绘)、下载、管理和GPS定位等功能。数据一旦下载下来,就可以脱离Internet网工作。所有这些操作均可以使用地理坐标(经纬度)精确地指定范围,也可以直观地在已经下载的卫片上用鼠标指定范围。一、显示 使用操作菜单的打开卫片数据包功能打开需要显示的卫片数据。工具安装时自带一个东北半球的数据包,该数据包包含东经0至180度,北纬0至90度的 Google Map第10层数据。卫星照片一共有18层(到目前为止),层数越大分辨率越高,相邻两层的数据量比例为平方,即某一层的数据量为n,则下一层的数据量为 n*n。安装时该数据包存放在与“卫片工具”相同的目录下。比如:c:\program files\lusg\卫片工具。 使用鼠标在卫片上的移动显示对应位置的地理坐标卫片包文件和卫片块标识。这些信息在工具的窗口栏显示。具体格式如下: 沈阳18:经度 123°19′52″(123.331264) 纬度41°57′18″(41.955078) trsqstsssrqrsqqsqs 。其中“沈阳18”为数据包文件名,该文件是在下载数据时形成的,数据包包含两个分别以.dat和.idx为后缀的同名文件,该示例中显示的数据包包含 “沈阳18.dat”和“沈阳18.idx”两个文件。 在卫片上按住鼠标左键拖动,放开后工具自动计算拖动开始和结束位置的地理坐标以及该范围内包含的卫片块,并弹出按经纬度处理窗口。该窗口可以指定需要处理的卫片层数、经纬度范围,并可以进行数据下载和打印。该窗口也可以从操作菜单的指定经纬度操作弹出。详细说明见下载部分。 本工具使用一个 access数据存放地名,该工具发行时提供一个地名,该地名也存放在与“卫片工具”相同的目录下。可以使用操作菜单下的选择地名选择该文件。选择了地名后,就可以使用“漫游至指定地”功能查找地名中的地名,并漫游到该地。如果没有地名使用这一功能也可以直接输入经纬度漫游到相应的地。 图上漫游:在卫片击鼠标左键,该就漫游到窗口的中央,重复使用该功能实现卫片显示的连续漫游。二、打印(喷绘) 本工具的打印(喷绘)功能也在指定经纬度操作窗口中实现。打印有三个不同的选项:模拟显示、打印和输出到文件。选择完指定打印机设置后工具按选择的输出参数输出数据。模拟显示窗口显示对应打印内容的缩放显示;打印直接输出到打印机;输出到文件就是按每页的内容输出到一组jpg文件中,文件名为 PrintFileXXX.JPG,这些文件包含有 Marge.ini文件中指定的x和y方向的重叠部分,单位为像素。得到这一组输出文件后就可以在其他的图像编辑软件(比如PhotoShop)中进行修饰处理,并输出。通过重叠的部分为最后拼接为挂图提供方便。三、下载 卫片的下载工具可以有两种方式启动,一是选择操作菜单的指定经纬度操作,二是在已有的卫片上按住鼠标左键拖动范围启动按经纬度操作窗口。 下载深度就是指需要下载哪层数据,选择范围是1-18,当前第18层为分辨率最高的。通过菜单启动系统不预置深度值,需要人工指定。 开始和结束经纬度是指需要处理的范围,可以人工输入,也可以通过在卫片上拖动鼠标获得。 下载按钮启动下载进程,启动前工具会根据指定的范围和下载深度计算该范围内的卫片块。如果事先已经选择好了需要下载的深度,然后再拖动鼠标系统自动计算这些块。块名会在右边的文本编辑框内显示出来。一共包含多少块,起始和终止块均会在范围上面显示出来。系统下载时同时启动20个进程, 卫片下载分两步完成,第一步下载图像块,生成一系列的LDA后缀的文件,如果一次下载不完,不要选择打包,下次可以接续下载。所有需要的图片(同一层) 都下载完后执行打包。第二步打包,形成Bag.dat和Bag.idx文件对,并保存在“卫片工具”目录下的temp子目录中。这两个文件使用时可以拷到任何地方,建议拷贝到你的专门保存卫片的目录中,并同时修改这两个文件名,比如改为“沈阳18.dat”和“沈阳18.idx”。这里之所以使用18是想记录该卫片数据包为沈阳第18层数据,以便于以后调用。 改变下载深度后,可以估算但不进行下载。这一功能使用计算块按钮。四、GPS定位 工具启动时根据“卫片工具”目录中的GPS.ini文件中指定的串口试图连接GPS,如果连接成功,工具在收到GPS定位信息后在卫片上显示一个黄色的十字标记指示GPS报告的位置,缺省情况下这会漫游到窗口中央。如果不需要这种跟踪可以通过操作菜单中的“GPS跟踪”菜单项取消跟踪。取消跟踪后,黄色十字标记会继续显示,但收到数据后不会自动定位到窗口中央。这个菜单项是

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爬虫与地理信息

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值