昨天尝试了几种获取坐标范围方式,效率都不太高。
昨天的看这里:arcpy获取国土用地坐标范围的几种尝试
考虑到最简便的方法是直接获取当前图层框的范围,然后把投影坐标转换成经纬度坐标是最快捷的,于是在CSDN找,确实有不少高斯投影转经纬度的文章
1、python实现高斯投影正反算
2、Python 高斯坐标转经纬度算法
经测试在我用的用地范围内,第一个误差最小
这里是高斯投影坐标转换经纬度代码,把参数更新成了CGCS2000的,差异很小。
'''
2000国家大地坐标系的大地测量基本常数分别为:
长半轴 a = 6378137 m
地球引力常数 GM =3.986004418×1014m3s-2
扁率f = 1/ 298.257222101 = 0.0033528106811823
地球自转角速度X =7.292115×10-5rad s-1
'''
def latlng2xy(latitude, longitude):
a = 6378137.0
e2 = 0.00669342162296594323
#将经纬度转换为弧度
latitude2Rad = (math.pi / 180.0) * latitude
beltNo = int((longitude + 1.5) / 3.0) #计算3度带投影度带号
L = beltNo * 3 #计算中央经线
l0 = longitude - L #经差
tsin = math.sin(latitude2Rad)
tcos = math.cos(latitude2Rad)
t = math.tan(latitude2Rad)
m = (math.pi / 180.0) * l0 * tcos
et2 = e2 * pow(tcos, 2)
et3 = e2 * pow(tsin, 2)
X = 111132.9558 * latitude - 16038.6496 * math.sin(2 * latitude2Rad) + 16.8607 * math.sin(
4 * latitude2Rad) - 0.0220 * math.sin(6 * latitude2Rad)
N = a / math.sqrt(1 - et3)
x = X + N * t * (0.5 * pow(m, 2) + (5.0 - pow(t, 2) + 9.0 * et2 + 4 * pow(et2, 2)) * pow(m, 4) / 24.0 + (
61.0 - 58.0 * pow(t, 2) + pow(t, 4)) * pow(m, 6) / 720.0)
y = 500000 + N * (m + (1.0 - pow(t, 2) + et2) * pow(m, 3) / 6.0 + (
5.0 - 18.0 * pow(t, 2) + pow(t, 4) + 14.0 * et2 - 58.0 * et2 * pow(t, 2)) * pow(m, 5) / 120.0)
return x, y+40000000
def xy2latlng(X, Y, L0):
iPI = 0.0174532925199433
a = 6378137.0
f= 0.0033528106811823
ZoneWide = 3 #按3度带进行投影
ProjNo = int(X / 1000000)
L0 = L0 * iPI
X0 = ProjNo * 1000000 + 500000
Y0 = 0
xval = X - X0
yval = Y - Y0
e2 = 2 * f - f * f #第一偏心率平方
e1 = (1.0 - math.sqrt(1 - e2)) / (1.0 + math.sqrt(1 - e2))
ee = e2 / (1 - e2) #第二偏心率平方
M = yval
u = M / (a * (1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256))
fai = u \
+ (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * math.sin(2 * u) \
+ (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * math.sin(4 * u) \
+ (151 * e1 * e1 * e1 / 96) * math.sin(6 * u)\
+ (1097 * e1 * e1 * e1 * e1 / 512) * math.sin(8 * u)
C = ee * math.cos(fai) * math.cos(fai)
T = math.tan(fai) * math.tan(fai)
NN = a / math.sqrt(1.0 - e2 * math.sin(fai) * math.sin(fai))
R = a * (1 - e2) / math.sqrt(
(1 - e2 * math.sin(fai) * math.sin(fai)) * (1 - e2 * math.sin(fai) * math.sin(fai)) * (1 - e2 * math.sin(fai) * math.sin(fai)))
D = xval / NN
#计算经纬度(弧度单位的经纬度)
longitude1 = L0 + (D - (1 + 2 * T + C) * D * D * D / 6 + (
5 - 2 * C + 28 * T - 3 * C * C + 8 * ee + 24 * T * T) * D * D * D * D * D / 120) / math.cos(fai)
latitude1 = fai - (NN * math.tan(fai) / R) * (
D * D / 2 - (5 + 3 * T + 10 * C - 4 * C * C - 9 * ee) * D * D * D * D / 24 + (
61 + 90 * T + 298 * C + 45 * T * T - 256 * ee - 3 * C * C) * D * D * D * D * D * D / 720)
#换换为deg
longitude = longitude1 / iPI
latitude = latitude1 / iPI
return latitude, longitude
用昨天第2种获取图层范围来获取投影范围,适合全覆盖,由于坐标转换有细微偏差,增加了一圈范围,这样就能全覆盖。
注意:昨天第1种获取图层框投影范围,是获取的屏幕显示范围,如果是需要局部范围也可以使用。
昨天的看这里:arcpy获取国土用地坐标范围的几种尝试
def get_extent(add = 0.0005):
mxd = arcpy.mapping.MapDocument("CURRENT")
layer = arcpy.mapping.ListLayers(mxd, ly_name)[0]
extent = str(layer.getExtent(False)).split()
for i in range(4):
extent[i]= float(extent[i])
extent = extent[:4]
latmin,lngmin = xy2latlng(extent[0],extent[1], 120) #上面的转换函数
latmax,lngmax = xy2latlng(extent[2],extent[3], 120)
return latmin-add,lngmin-add,latmax+add,lngmax+add
测试一下,够快了!
if __name__ == '__main__':
s_time=time.time()
ly_name = '佴池三调'
ex = get_extent()
e_time=time.time()
print("耗时: %.4f s!" % (e_time - s_time))
>>>耗时: 0.0040 s!
画框子看看,扩了一点范围
#画个范围框
def kuang(ymin,xmin,ymax,xmax):
kuang = [[xmin,ymin],[xmin,ymax],[xmax,ymax],[xmax,ymin]]
mxd = arcpy.mapping.MapDocument("CURRENT")
sd_layer = arcpy.mapping.ListLayers(mxd, ly_name)[0]
path = sd_layer.workspacePath
coordinate = arcpy.SpatialReference(4490) #CGCS2000
arcpy.CreateFeatureclass_management (path, 'k_dian',"POINT", "", "","", coordinate)
rows=arcpy.InsertCursor('k_dian')
for i in range(len(kuang)):
row = rows.newRow()
vertex = arcpy.CreateObject("Point")
vertex.X = kuang[i][0]
vertex.Y = kuang[i][1]
row.shape = vertex
rows.insertRow(row)
arcpy.PointsToLine_management("k_dian", path+'\\kuang',"","" ,"CLOSE" )
kuang(ex[0],ex[1],ex[2],ex[3])