#!/usr/bin/python
#coding=GB2312
OGR-Geometry and Projection
几何对象与地图投影的使用。
by [email protected], 2016-04-25.
OGR矢量库:简单的矢量数据读写,是GDAL的一部分。
相关模块:
Numeric:高速的数组处理,对栅格数据尤其重要
NumPy:下一代的Numeric
更强大的gis库 http://www.gispython.org/
导入库
from osgeo import gdal, gdalconst
from osgeo.gdalconst import *
import gdal, gdalconst
from osgeo import ogr
建立新的几何对象
建立空的geometry对象:ogr.Geometry,定义各种不同的geometry使用的方法是不一样的(point, line, polygon, etc)。
新建点对象-point
使用方法AddPoint(
point = ogr.Geometry(ogr.wkbPoint)
point.AddPoint(10,20)
<osgeo.ogr.Geometry; proxy of <Swig Object of type 'OGRGeometryShadow *' at 0x7f2d0812d240> >
#help(point)
str(point)
'POINT (10 20 0)'
新建线对象-line
- 使用AddPoint(
, , [ ])添加点。 - 使用SetPoint(
, , , [ ])更改点的坐标。
例如下面这段代码,更改了0号点的坐标:
line = ogr.Geometry(ogr.wkbLineString)
line.AddPoint(10,10)
line.AddPoint(20,20)
line.SetPoint(0,30,30) #(10,10) -> (30,30)
str(line)
'LINESTRING (30 30 0,20 20 0)'
统计所有点的数目
print(line.GetPointCount())
2
读取0号点的x坐标和y坐标
print(line.GetX(0))
print(line.GetY(0))
30.0
30.0
新建多边形-polygon
首先要新建环(ring),然后把环添加到多边形对象中。
如何创建一个ring?先新建一个ring对象,然后向里面逐个添加点。
ring = ogr.Geometry(ogr.wkbLinearRing)
ring.AddPoint(0,0)
ring.AddPoint(100,0)
ring.AddPoint(100,100)
ring.AddPoint(0,100)
结束的时候,用CloseRings关闭ring,或者将最后一个点的坐标设定为与第一个点相同。
ring.CloseRings()
#ring.AddPoint(0,0)
str(ring)
'LINEARRING (0 0 0,100 0 0,100 100 0,0 100 0,0 0 0)'
下面举一个例子,创建一个方框。
这是个polygon对象,又例外两层ring构成。
outring = ogr.Geometry(ogr.wkbLinearRing)
outring.AddPoint(0,0)
outring.AddPoint(100,0)
outring.AddPoint(100,100)
outring.AddPoint(0,100)
outring.AddPoint(0,0)
inring = ogr.Geometry(ogr.wkbLinearRing)
inring = ogr.Geometry(ogr.wkbLinearRing)
inring.AddPoint(25,25)
inring.AddPoint(75,25)
inring.AddPoint(75,75)
inring.AddPoint(25,75)
inring.CloseRings()
polygon = ogr.Geometry(ogr.wkbPolygon)
polygon.AddGeometry(outring)
polygon.AddGeometry(inring)
0
str(polygon)
'POLYGON ((0 0 0,100 0 0,100 100 0,0 100 0,0 0 0),(25 25 0,75 25 0,75 75 0,25 75 0,25 25 0))'
最后三句话比较重要,就是先建立一个polygon对象,然后添加外层ring和内层ring。
下面这句话可以帮你数数,polygon能有几个ring。
print(polygon.GetGeometryCount())
2
从polygon中读取ring,index的顺序和创建polygon时添加ring的顺序相同。
outring = polygon.GetGeometryRef(0)
inring = polygon.GetGeometryRef(1)
print("OutRing: ",str(outring))
print("InRing: ",str(inring))
OutRing: LINEARRING (0 0 0,100 0 0,100 100 0,0 100 0,0 0 0)
InRing: LINEARRING (25 25 0,75 25 0,75 75 0,25 75 0,25 25 0)
创建复合几何形状-multi geometry
例如:MultiPoint, MultiLineString, MultiPolygon。用AddGeometry把普通的几何形状加到复合几何形状中。
multipoint = ogr.Geometry(ogr.wkbMultiPoint)
point = ogr.Geometry(ogr.wkbPoint)
point.AddPoint(10,10)
multipoint.AddGeometry(point)
point.AddPoint(20,20)
multipoint.AddGeometry(point)
0
str(multipoint)
'MULTIPOINT (10 10 0,20 20 0)'
读取MultiGeometry中的Geometry
方法和从Polygon中读取ring是一样的,可以说Polygon是一种内置的MultiGeometry。
- 不要删除一个已存在的Feature的Geometry,会把python搞崩溃的。
- 只能删除脚本运行期间创建的Geometry,比方说手工创建出来的,或者调用其他函数自动创建的。就算这个Geometry已经用来创建别的Feature,你还是可以删除它。
例如:Polygon.Destroy()
关于投影-Projection
使用SpatialReference对象。
- 多种多样的Projections,GDAL支持WKT, PROJ.4, ESPG, USGS, ESRI.prj
- 可以从layer和Geometry中读取Projections。
例如:
spatialRef = layer.GetSpatialRef()
spatialRef = geom.GetSpatialReference()
投影信息一般存储在.prj文件中,如果没有这个文件,上述函数返回None。
建立一个新的Projection
首先导入osr库,之后使用osr.SpatialReference()创建SpatialReference对象。 用下列语句向SpatialReference对象导入投影信息。
ImportFromWkt(<wkt>)
ImportFromEPSG(<epsg>)
ImportFromProj4(<proj4>)
ImportFromESRI(<proj_lines>)
ImportFromPCI(<proj>, <units>, <parms>)
ImportFromUSGS(<proj_code>, <zone>)
ImportFromXML(<xml>)
导出Projection
使用下面的语句可以导出为字符串
ExportToWkt()
ExportToPrettyWkt()
ExportToProj4()
ExportToPCI()
ExportToUSGS()
ExportToXML()
对一个几何形状Geometry进行投影变换,要先初始化两个Projection,然后创建一个CoordinateTransformation对象,用它来做变换。
from osgeo import osr
sourceSR = osr.SpatialReference()
sourceSR.ImportFromEPSG(32612) #UTM 12N WGS84
targetSR = osr.SpatialReference()
targetSR.ImportFromEPSG(4326) #Geo WGS84
coordTrans = osr.CoordinateTransformation(sourceSR, targetSR)
对几何对象进行投影变换
print("Projection transform:")
print("Before:", multipoint)
#geom.Transform(coordTrans)
multipoint.Transform(coordTrans)
print("After :", multipoint)
Projection transform:
Before: MULTIPOINT (-115.489778556511723 0.0 0,-115.489778556511723 0.0 0)
After : MULTIPOINT (-115.489778556511723 0.0 0,-115.489778556511723 0.0 0)
据说,在windows里面跑不通(http://n2.nabble.com/PROJ-4-EPSG-28992-td2033665.html)
我在linux(Ubuntu15.04)里面没问题。
另外还有几个要注意的地方:
- 要在适当的时候编辑Geometry,投影变换之后最好就不要再动了吧。
- 对一个数据源DataSource里面的所有Geometry做投影变换,得一个一个来,用个循环吧。
将投影参数写入.prj文件。
首先MorphToESRI(),转成字符串,然后开个文本文件往里面写就行了。
targetSR.MorphToESRI()
sr_wkt = targetSR.ExportToWkt()
print(sr)
file = open('test.prj', 'w')
file.write(sr_wkt)
file.close()
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]