GDAL 实现创建几何对象

^ 关注我,带你一起学GIS ^

前言

几何对象作为图层要素对象,具有点、线、面、多点、多线、多线等多种类型。每种类型都有自己独特的结构,在GIS开发中,需要掌握其组成结构和创建方式。

在之前的文章中讲了如何使用GDAL或者ogr2ogr工具将txt以及csv文本数据转换为Shp格式,本篇教程在之前一系列文章的基础上讲解如何使用GDAL实现创建几何对象。

如果你还没有看过,建议从以上内容开始。

1. 开发环境

本文使用如下开发环境,以供参考。

时间:2025年

系统:Windows 11

Python:3.11.7

GDAL:3.11.1

2. 创建点几何对象

定义一个方法CreatePoint用于创建点Shp图层,接收一个参数pointPath指向点文件路径。

python 复制代码
"""
说明:创建点Shp图层
参数:
    -pointPath:点文件路径
"""
def CreatePoint(pointPath):

GDAL中使用Geometry方法创建点几何对象,需要传入一个几何对象类型参数,创建点时该参数为ogr.wkbPointGeometryTypeToName方法可以获取几何对象类型名称,如下输出"Point"。接着使用AddPoint将坐标点添加到点对象中。

ini 复制代码
# 创建点几何对象
pointGeometry = ogr.Geometry(ogr.wkbPoint)
geomeTypeName = ogr.GeometryTypeToName(pointGeometry.GetGeometryType())
# print(f"几何对象名称:{geomeTypeName}")
# 添加坐标点
pointGeometry.AddPoint(100.225207,27.665721)

如下为创建点Shp图层完整方法。

python 复制代码
"""
说明:创建点几何对象
参数:
    -pointPath:点文件路径
"""
def CreatePoint(pointPath):
    print("开始创建点对象")

    # 添加shp数据驱动
    shpDriver = gdal.GetDriverByName("ESRI Shapefile")

    checkShpPath(pointPath,shpDriver)

    # 创建shp数据源
    shpDataSource = shpDriver.CreateDataSource(pointPath)
    if shpDataSource is None:
        print("无法创建点Shp数据源,请检查文件!")
        return False

    # 创建点数据图层
    pointLayer = shpDataSource.CreateLayer("point",geom_type=ogr.wkbPoint)

    # 添加id字段
    fieldDefn = ogr.FieldDefn("id",ogr.OFTInteger)
    pointLayer.CreateField(fieldDefn)

    # 获取要素结构
    featureDefn = pointLayer.GetLayerDefn()

    # 创建要素对象
    pointFeature = ogr.Feature(featureDefn)

    points = [
       "100.225207,27.665721",
       "105.330257,29.948948",
       "105.848739,23.856316",
       "99.567134,23.892995"
    ]
    # pointGeometry.AddPoint(100.225207,27.665721)
    for i,point in enumerate(points):
        # print(f"点:{point}")
        res = point.split(",")
        # print(f"点:{res}")

        # 创建点几何对象
        pointGeometry = ogr.Geometry(ogr.wkbPoint)
        geomeTypeName = ogr.GeometryTypeToName(pointGeometry.GetGeometryType())
        # print(f"几何对象名称:{geomeTypeName}")

        pointGeometry.AddPoint(float(res[0]),float(res[1]))

        pointFeature.SetGeometry(pointGeometry)
        pointFeature.SetField("id",i)
        pointLayer.CreateFeature(pointFeature)

3. 创建线几何对象

定义一个方法CreatePolyline用于创建点Shp图层,接收一个参数polylinePath指向线文件路径。

python 复制代码
"""
说明:创建线Shp图层
参数:
    -polylinePath:线文件路径
"""   
def CreatePolyline(polylinePath):

使用Geometry方法创建线几何对象,将几何对象类型改为ogr.wkbLineString。接着使用AddPoint将坐标点添加到线对象中。

ini 复制代码
# 创建线几何对象
polylineGeometry = ogr.Geometry(ogr.wkbLineString)
geomeTypeName = ogr.GeometryTypeToName(polylineGeometry.GetGeometryType())
# 添加坐标点
polylineGeometry.AddPoint(100.225207,27.665721)
polylineGeometry.AddPoint(105.330257,29.948948)
polylineGeometry.AddPoint(105.848739,23.856316)
polylineGeometry.AddPoint(99.567134,23.892995)

如下为创建线Shp图层完整方法。

scss 复制代码
"""
说明:创建线Shp图层
参数:
    -polylinePath:线文件路径
"""   
def CreatePolyline(polylinePath):
    print("开始创建线对象")

    # 添加shp数据驱动
    shpDriver = gdal.GetDriverByName("ESRI Shapefile")

    checkShpPath(polylinePath,shpDriver)

    # 创建shp数据源
    shpDataSource = shpDriver.CreateDataSource(polylinePath)
    if shpDataSource is None:
        print("无法创建点Shp数据源,请检查文件!")
        return False

    # 创建线数据图层
    polylineLayer = shpDataSource.CreateLayer("polyline",geom_type=ogr.wkbLineString)

    # 添加id字段
    fieldDefn = ogr.FieldDefn("id",ogr.OFTInteger)
    polylineLayer.CreateField(fieldDefn)

    # 获取要素结构
    featureDefn = polylineLayer.GetLayerDefn()

    # 创建要素对象
    pointFeature = ogr.Feature(featureDefn)
    points = [
       "100.225207,27.665721",
       "105.330257,29.948948",
       "105.848739,23.856316",
       "99.567134,23.892995",
       "100.225207,27.665721"
    ]
    # pointGeometry.AddPoint(100.225207,27.665721)
    # 创建线几何对象
    polylineGeometry = ogr.Geometry(ogr.wkbLineString)
    geomeTypeName = ogr.GeometryTypeToName(polylineGeometry.GetGeometryType())
    polylineGeometry.AddPoint(100.225207,27.665721)
    polylineGeometry.AddPoint(105.330257,29.948948)
    polylineGeometry.AddPoint(105.848739,23.856316)
    polylineGeometry.AddPoint(99.567134,23.892995)
    # print(f"几何对象名称:{geomeTypeName}")
    for i,point in enumerate(points):
        # print(f"点:{point}")
        res = point.split(",")
        # print(f"点:{res}")

        polylineGeometry.AddPoint(float(res[0]),float(res[1]))

    pointFeature.SetGeometry(polylineGeometry)
    pointFeature.SetField("id",1)

    polylineLayer.CreateFeature(pointFeature)

4. 创建面几何对象

定义一个方法CreatePolygon用于创建面Shp图层,接收一个参数polygonPath指向线文件路径。

python 复制代码
"""
说明:创建面Shp图层
参数:
    -polygonPath:面文件路径
"""     
def CreatePolygon(polygonPath):

在创建面几何对象之前需要先创建环形几何对象,类型参数为ogr.wkbLinearRing

scss 复制代码
# 创建一个环形Geometry
ringGeometry = ogr.Geometry(ogr.wkbLinearRing)
geomeTypeName = ogr.GeometryTypeToName(ringGeometry.GetGeometryType())

ringGeometry.AddPoint(100.225207,27.665721)
ringGeometry.AddPoint(105.330257,29.948948)
ringGeometry.AddPoint(105.848739,23.856316)
ringGeometry.AddPoint(99.567134,23.892995)

然后使用Geometry方法创建线面何对象,将几何对象类型改为ogr.wkbPolygon。接着使用AddGeometry将环形对象添加到面中。

ini 复制代码
# 创建面几何对象
polygonGeometry = ogr.Geometry(ogr.wkbPolygon)
# 添加环形对象
polygonGeometry.AddGeometry(ringGeometry)

此外还有一种带有孔洞的多边形需要注意一下,此时环形几何对象分为内环和外环两种类型。

scss 复制代码
# 创建一个外环Geometry
outRingGeometry = ogr.Geometry(ogr.wkbLinearRing)

outRingGeometry.AddPoint(100.225207,27.665721)
outRingGeometry.AddPoint(105.330257,29.948948)
outRingGeometry.AddPoint(105.848739,23.856316)
outRingGeometry.AddPoint(99.567134,23.892995)
outRingGeometry.AddPoint(100.225207,27.665721)
# 关闭环状几何
# outRingGeometry.CloseRings()

# 创建一个内环Geometry
inRingGeometry = ogr.Geometry(ogr.wkbLinearRing)

inRingGeometry.AddPoint(100.415207,27.665721)
inRingGeometry.AddPoint(104.550257,27.665721)
inRingGeometry.AddPoint(104.550257,24.456316)
inRingGeometry.AddPoint(100.415207,24.456316)
inRingGeometry.AddPoint(100.415207,27.665721)
# 关闭环状几何
# inRingGeometry.CloseRings()

# 创建面几何对象
polygonGeometry = ogr.Geometry(ogr.wkbPolygon)
polygonGeometry.AddGeometry(outRingGeometry)
polygonGeometry.AddGeometry(inRingGeometry)

对于面几何对象创建完成后需要关闭环状几何,可以调用几何对象CloseRings()或者在最后添加与第一个坐标相同点进行关闭。

scss 复制代码
outRingGeometry.CloseRings()
inRingGeometry.CloseRings()

如下为创建面Shp图层完整方法。

python 复制代码
"""
说明:创建面Shp图层
参数:
    -polygonPath:面文件路径
"""     
def CreatePolygon(polygonPath):
    print("开始创建面对象")

    # 添加shp数据驱动
    shpDriver = gdal.GetDriverByName("ESRI Shapefile")

    checkShpPath(polygonPath,shpDriver)

    # 创建shp数据源
    shpDataSource = shpDriver.CreateDataSource(polygonPath)
    if shpDataSource is None:
        print("无法创建点Shp数据源,请检查文件!")
        return False

    # 创建面数据图层
    polygonLayer = shpDataSource.CreateLayer("polygon",geom_type=ogr.wkbPolygon)

    # 添加id字段
    fieldDefn = ogr.FieldDefn("id",ogr.OFTInteger)
    polygonLayer.CreateField(fieldDefn)

    # 获取要素结构
    featureDefn = polygonLayer.GetLayerDefn()

    # 创建要素对象
    polygonFeature = ogr.Feature(featureDefn)

    points = [
       "100.225207,27.665721",
       "105.330257,29.948948",
       "105.848739,23.856316",
       "99.567134,23.892995",
       "100.225207,27.665721"
    ]
    # pointGeometry.AddPoint(100.225207,27.665721)
    # 创建一个环形Geometry
    ringGeometry = ogr.Geometry(ogr.wkbLinearRing)
    geomeTypeName = ogr.GeometryTypeToName(ringGeometry.GetGeometryType())

    # print(f"几何对象名称:{geomeTypeName}")
    for i,point in enumerate(points):
        print(f"点:{point}")
        res = point.split(",")
        print(f"点:{res}")

        ringGeometry.AddPoint(float(res[0]),float(res[1]))

    # 关闭环状几何
    # or ringGeometry.CloseRings()

    # 创建面几何对象
    polygonGeometry = ogr.Geometry(ogr.wkbPolygon)
    polygonGeometry.AddGeometry(ringGeometry)

    polygonFeature.SetGeometry(polygonGeometry)
    polygonFeature.SetField("id",1)

    polygonLayer.CreateFeature(polygonFeature)

5. 总结

创建图层前第一步都是要需要获取数据驱动,如Shp数据驱动为"ESRI Shapefile"

ini 复制代码
# 添加shp数据驱动
shpDriver = gdal.GetDriverByName("ESRI Shapefile")

然后便可以创建数据源,并检查数据源是否创建成功。

python 复制代码
# 创建shp数据源
shpDataSource = shpDriver.CreateDataSource(polygonPath)
if shpDataSource is None:
    print("无法创建点Shp数据源,请检查文件!")
    return False

创建目标图层,"polygon"为自定义参数,geom_type为图层几何类型,可以根据实际需求进行修改。此外,创建图层方法还可以传入一个坐标系参数,例子中就不展示了。

ini 复制代码
# 创建面数据图层
polygonLayer = shpDataSource.CreateLayer("polygon",geom_type=ogr.wkbPolygon)

图层创建完成之后,便可以添加一些属性表结构。通过ogr.FieldDefn创建字段域,并通过图层方法CreateField创建字段,使用方法GetLayerDefn()获取要素域。

ini 复制代码
# 添加id字段
fieldDefn = ogr.FieldDefn("id",ogr.OFTInteger)
polygonLayer.CreateField(fieldDefn)

# 获取要素结构
featureDefn = polygonLayer.GetLayerDefn()

# 创建要素对象
polygonFeature = ogr.Feature(featureDefn)

创建几何对象。

ini 复制代码
ringGeometry = ogr.Geometry(ogr.wkbLinearRing)
geomeTypeName = ogr.GeometryTypeToName(ringGeometry.GetGeometryType())

for i,point in enumerate(points):
    # print(f"点:{point}")
    res = point.split(",")
    # print(f"点:{res}")

    ringGeometry.AddPoint(float(res[0]),float(res[1]))

# 关闭环状几何
# or ringGeometry.CloseRings()

# 创建面几何对象
polygonGeometry = ogr.Geometry(ogr.wkbPolygon)
polygonGeometry.AddGeometry(ringGeometry)

将几何对象和属性字段添加到要素中,之后使用图层方法CreateFeature创建图层要素。

scss 复制代码
polygonFeature.SetGeometry(polygonGeometry)
polygonFeature.SetField("id",1)

polygonLayer.CreateFeature(polygonFeature)

至此,大功告成。

ArcMap中打开成果显示如下。

小提示:

  1. 例子中创建的数据图层并未加上坐标信息,有兴趣的读者可以自行实现。
  2. 文中只实现了点、线、面对象,对于多点、多线和多面几何类型也留给感兴趣的读者自行实现!

对于GDAL中几何对象类型不太了解的同学可以参考文章:GDAL 数据类型大全

参考资料[1]

GDAL 数据类型大全

OpenLayers示例数据下载,请在公众号后台回复:ol数据

全国信息化工程师-GIS 应用水平考试资料,请在公众号后台回复:GIS考试

GIS之路 公众号已经接入了智能 助手,可以在对话框进行提问,也可以直接搜索历史文章进行查看。

都看到这了,不要忘记点赞、收藏 + 关注

本号不定时更新有关 GIS开发 相关内容,欢迎关注


GeoTools 开发合集(全)

OpenLayers 开发合集

GDAL 实现自定义数据坐标系

GDAL 实现矢量数据读写

GDAL 数据类型大全

GDAL 实现 GIS 数据读取转换(全)

GIS 数据转换:使用 GDAL 将 Shp 转换为 GeoJSON 数据

GIS 数据转换:使用 GDAL 将 GeoJSON 转换为 Shp 数据

GIS 数据转换:使用 GDAL 将 TXT 转换为 Shp 数据

使用命令行工具 ogr2ogr 将 CSV 转换为 Shp 数据(二)

GDAL 实现将 CSV 转换为 Shp 数据(一)

相关推荐
liulilittle13 小时前
CLANG 交叉编译
linux·服务器·开发语言·前端·c++
自信阿杜13 小时前
跨标签页数据同步完全指南:如何选择最优通信方案
前端·javascript
牛马11114 小时前
WidgetsFlutterBinding.ensureInitialized()在 Flutter Web 端启动流程的影响
java·前端·flutter
Captaincc14 小时前
2025: The year in LLMs
前端·vibecoding
指尖跳动的光14 小时前
Vue的nextTick()方法
前端·javascript·vue.js
码事漫谈14 小时前
可能,AI早都觉醒了
前端
qq_4061761415 小时前
JS 事件循环(Event Loop)
开发语言·前端·javascript
Codebee15 小时前
ooder A2UI ES6版本正式发布:现代化模块架构,MIT开源许可
前端
Devin_chen15 小时前
4.前端使用Node + MongoDB + Langchain消息管理与聊天历史存储
前端·langchain