OGR中的数据结构

image.png

driver解析数据的驱动

  1. # 【方法一】从已有数据源中获取驱动变量
  2. ds = ogr.open(r'D:\....\...shp')
  3. driver = ds.GetDriver()
  4. # 【方法二】通过名称获取
  5. json_driver = ogr.GetDrverByName('GeoJSON')
  6. # 获得驱动名的两种方法
  7. # 1. OGR网站上有介绍,通过GDAL/ORG自带的ogrinfo
  8. # 2. 代码中提供的print_drivers函数来获取驱动程序的名字

datasource管理数据源

(1)创建数据源
有了驱动程序之后,提供数据源名称来使用它创建一个空的数据源。新创建的数据源会自动打开等待写入

  1. # 创建一个功能齐全的SpatialLite数据源,而不是使用SQLite
  2. fn = "filename"
  3. driver = ogr.GetDriverByName("SQLite")
  4. # 创建新的数据源时,不能覆盖现有的数据源。如果你的代码可能会覆盖现有数据,那么在创建新数据之前需要删除旧数据
  5. if os.path.exists(fn):
  6. driver.DeleteDataSource(fn)
  7. ds= driver.CreateDataSource(fn,
  8. options=[ #创建选项:传递一个字符串列表(参数在OGR网站上有文档介绍)
  9. 'SPATIALITE=yes'
  10. ]
  11. )
  12. if ds is None:
  13. #【注意】如果数据源没有创建成功,那么CreateDataSource函数会返回为空。如果为空对象,之后使用会报AttributeError错误
  14. sys.exit('Could not create {0}'.formaat(json_fn ) )

(2)删除数据源

  1. datasource.Destory() #关闭
  2. del datasource # 删除datasource
  3. """ 删除ds变量强制关闭文件,并将所有的编辑成果写入磁盘中
  4. 【注意】删除图层变量并不会触发这个操作,必须关闭数据源才行
  5. 【备注】如果想保持数据源打开的话,可以通过图层对象或者数据源对象调用ds.SyncToDisk()
  6. 【警告】为了使你的编辑写入到磁盘中,必须关闭文件或者调用SyncToDisk函数。如果没有这么做,并且在交互环境中还打开数据源,那么你会很失望地发现创建了一个空的数据集
  7. """

layer管理图层

  1. layer = datasource.GetLayer(0) #根据下标来获取图层(对于shp而言只有一个图层)
  2. layer.GetGeomType() #图层几何类型
  3. n = layer.GetFeatureCount() #要素数量
  4. extent = layer.GetExtent() #上下左右边界
  5. readedNum = GetFeaturesRead() #已经读取多少条Feature
  6. layer.ResetReading() #重置内部feature指针,指向FID=0的要素
  7. layer.GetSpatialRef() #使用wkt文本表示空间参考系统的实例
  8. layer.schema #获取FieldDefn对象列表(属性名)

feature管理要素类

从Layer中获得feature
  1. # 1. 【获得图层中的要素】
  2. feature = layer.GetFeature(0)
  3. # 2. 【获取图层中所有要素】
  4. feat = layer.GetNextFeature()
  5. while feat:
  6. feat = layer.GetNextFeature()
  7. layer.ResetReading()

更新要素

要素更新操作也大同小异,只不过你操作的是图层中的现有要素,而不是一个空白的对象

  1. # 【例子】为图层的每一个要素添加一个唯一的ID
  2. layer.CreateField( # 为图层添加一个ID字段
  3. ogr.FieldDefn('ID', ogr.OFTInteger)
  4. )
  5. n = 1
  6. for feat in layer:
  7. feat.SetField('ID', n) #设置字段的值
  8. layer.SetFeature(feat) #将数值传递给SetFeature函数,来更新图层中的要素信息(这里不是CreateFeature函数)
  9. n += 1

删除要素

删除要素更容易,需要知道的就是待删除要素的FID

  1. #【例子】删除字段City_Name为"Seattle"的要素
  2. # 找到目标的FID进行删除
  3. for feat in layer:
  4. if feat.GetField('City_Name')=='Seattle':
  5. layer.DeleteFeature(feat.GetFID() ) #删除操作
  6. """
  7. 【但是】
  8. 1. 某些特定的数据格式使用此方式并不能完全删除要素。
  9. 2. 你可能看不出,有时要素只是被标记为删除了,而不是被完全抛出,它仍然还潜伏着。
  10. 3. 正因如此,你不会看到其他要素被分配到刚才删除的FID
  11. 4. 这意味着,如果已经删除了很多要素,在文件中可能存在大量不必要的已用空间
  12. 【所以】删除这些要素可以回收对应的空间
  13. 【如何回收对应空间】如果你有一些关系数据库的经验,应该熟悉这一点。它类似于在微软的Access数据库上运行压缩和修复或在PostgreSQL数据库中使用重组功能(VACUUM)
  14. 【具体做法】打开数据源,然后执行一条SQL语句来压缩数据库(不同的数据格式回收的方法不同)
  15. """
  16. ds.ExecuteSQL('REPACK' + layer.GetName() ) #shapefile格式回收方式
  17. ds.ExecuteSQL('RECOMPUTE EXTENT ON' + layer.GetName() ) #确保空间范围更新
  18. # 当现有要素发生改变或被删除后,它不会更新元数据中的空间范围

关闭要素
  1. feature.Destory() #关闭

创建要素

往现有图层中添加新要素和往全新的图层中添加要素的操作一样,具体请看示例

【步骤】
1.基于图层字段创建一个空要素,填充它
2.然后把它插入到该图层

geometry管理要素的几何属性

Geometry的几何属性

【org.Geometry中的几何类型】ogr.wkbPoint、org.wkbLineString、org.wkbPolygon等,请看wkt

  1. # 获得Geometry的几何属性
  2. layer.GetGeomType() == ogr.wkbPolygon
  3. layer.GetGeometryName()

从Feature获取Geometry
  1. # 两种方法
  2. geometry = feature.geometry()
  3. geometry = feat.GetGeometryRef()

常用方法
  1. geom.GetGeometryName() #要素类型
  2. geom.GetPointCount() #要素点个数
  3. geom.GetX(0);geom.GetY(0);geom.GetZ(0) #获得第一个坐标点的X、Y、Z
  4. print(geom) #打印出所有点
  5. geom.ExportToWkt() #导出WKT

创建Geometry

请看示例

field管理要素的属性字段

【字段类型常量】

有一些不同的属性字段类型,但并不是每一种字段类型都支持所有的数据格式。这时候用于描述各种数据格式的在线文档就派上用场了。

字段数据类型 OGR常量
Integer OFTInteger
List of integers OFTIntegerList
Floating point number OFTReal
List of floating point numbers OFTRealList
String OFTString
List of strings OFTStringList
Date OFTDate
Time of day OFTTime
Date and time OFTDateTime

创建字段

在Layer中新建属性字段

  1. # 创建并添加第一个属性字段
  2. coord_fld = ogr.FieldDefn('X', ogr.OFTReal)
  3. # 设置限制
  4. coord_fld.SetWidth(8)
  5. coord_fld.SetPrecision(3)
  6. out_lyr.CreateField(coord_fld)
  7. # 重用FieldDefn对象来创建第二个字段
  8. coor_fld.SetName('Y')
  9. out_lyr.CreateField(coord_fld)

更改属性定义

【函数】AlterFieldDefn(iField, field_def, nFlags)
【作用】用新字段的规则替换现有的字段
【参数说明】

  1. iField是想改变的属性字段对应的索引值
  2. field_def是新属性字段的定义对象
  3. nFlags是一个整数,是下表中的一个或多个常数的总和

【用于指明字段定义的哪个属性可以更改的标记,如果想使用多个,一起添加即可】

需要更改的字段属性 OGR常量
Field name only ALTER_NAME_FLAG
Field type only ALTER_TYPE_FLAG
Field width and/or precision only ALTER_WIDTH_PRECISION_FLAG
All of the above ALTER_ALL_FLAG
  1. # 【例子一】 更改原字段的名字
  2. index = layer.GetLayerDefn().GetFieldIndex('NAME') #获取字段的索引值
  3. fld_defn = ogr.FieldDefn('City_Name', ogr.OFTString) #创建新属性的字段定义
  4. layer.AlterFieldDefn(index, fld_defn, ogr.ALTER_NAME_FLAG)
  5. # 【例子二】 更改字段的多个属性,例如名称和精度
  6. lyr_defn = layer.GetLayerDefn()
  7. index = lyr_defn.GetFieldIndex('X')
  8. width = lyr_defn.GetFieldDefn(index).GetWidth()
  9. fld_defn = ogr.FieldDefn('X_coord', ogr.OFTReal)
  10. fld_defn.SetWidth(width)
  11. fld_defn.SetPrecision(4)
  12. flag = ogr.ALTER_NAME_FLAG + ogr.ALTER_WIDTH_PRECISION_FLAG
  13. layer.AlterFieldDefn(index, fld_defn, flag)
  14. """【注意】在此例子中创建新的字段定义时使用的是原始字段宽度
  15. 如果没有为原始数据设置足够大的字段宽度,结果将不正确
  16. 为了解决这个问题,需要使用与原始数据一样的字段宽度
  17. 为了使更改的精度生效,所有记录必须重写
  18. 为数据设置一个比它自身更高的精度并不会提高精度,因为数据不能凭空产生,但如果设置的精度不够高,精度就会降低
  19. """

其他
  1. feature.GetFieldCount() # 属性总数
  2. feature.keys() # 属性名
  3. feat.GetField('AREA') # 获取字段
  4. feature.GetFieldAsString("FID") # 获取字段成string

经验

1.没能为GeoJSON文件设置一个精度
2.想在shapefile中设置字段精度,必须设置字段宽度
3.设置字段的默认值:FieldDefn.SetDefault("我是默认值")

wkt

WKB(二进制Well-KnownBinary),用于不同软件程序间进行几何要素类型转换的一种二进制表示标准。
因为它是二进制格式,所以人们无法直接阅读获取其表示的内容,但是熟知文本格式(Well-Known Text,WKT)可以阅读。

几何要素类型 对应OGR常量
Point wkbPoint
Multipoint wkbMultiPoint
Line wkbLineString
Multiline wkbMultiLineString
Polygon wkbPolygon
Multipolygon wkbMultiPolygon
Unknown geometry type wkbUnknown(图层如果有多种几何类型就返回wkbUnknown)
No geometry wkbNone