基本原理:想要为某个线状要素类中的所有线要素生成等距离节点,可以按照以下步骤实现:
- 读取要素折点;
- 结合折点间距离大小以及直线上点与距离关系(通过相似三角形)求得可满足预期距离的点的坐标位置,将所得点坐标信息保存为xls文件;
- 应用ArcGIS读取xls,生成点状要素类。
以下为生成等距离节点xls文件得代码,由于xls最多可存储65535行,本代码会将多余的部分存到同一份xls文件的下一个表中。
# -*- coding: utf-8 -*-
import sys, math
import arcpy
import xlwt
reload(sys)
sys.setdefaultencoding('utf8')
fc_path = unicode("./xxx.mdb/line", "utf-8")
# 根据两点坐标和由一点出发的距离,求第三点坐标
def calPosition(p1, p2, d):
p1_x = p1[0]
p1_y = p1[1]
p2_x = p2[0]
p2_y = p2[1]
d_12 = math.sqrt(math.pow((p2_x - p1_x), 2) + math.pow((p2_y - p1_y), 2))
d_x = (d * (p2_x - p1_x)) / d_12
d_y = (d * (p2_y - p1_y)) / d_12
x = p1_x + d_x
y = p1_y + d_y
return (x, y)
# 计算一条折线总长度及刨除最后一部分的折线长度
def calLength(points):
length_total = 0
length_exclude_last_segment = 0
for i in range(0, len(points)-1):
p1 = points[i]
p2 = points[i+1]
p1_x = p1[0]
p1_y = p1[1]
p2_x = p2[0]
p2_y = p2[1]
d_12 = math.sqrt(math.pow((p2_x - p1_x), 2) + math.pow((p2_y - p1_y), 2))
length_total += d_12
if i!= (len(points)-2):
length_exclude_last_segment += d_12
return length_total, length_exclude_last_segment
# 根据切分距离生成折点
def splitLine(points, d):
vertex_generated = [points[0]]
point_index = 1 # 点集中即将访问的下一个点
# 未遍历完折线所有折点时
while point_index < len(points):
points_sub = []
points_sub.append(vertex_generated[-1]) # 新生成折点作为起点
d_balance = 0
point_index_copy = point_index
# 从当前位置向后遍历,在总长度未满足条件前不断添加折点
for i in range(point_index_copy, len(points)):
points_sub.append(points[i])
length_total, length_exclude_last_segment = calLength(points_sub)
# print point_index, length_total, length_exclude_last_segment
if length_total >= d:
d_balance = d - length_exclude_last_segment
point_index = i
break
else:
point_index = i + 1
# 如果最后一段折线长度大于0,可以排除遍历到最后折点不足情况
if d_balance > 0:
p1 = points_sub[-2]
p2 = points_sub[-1]
vertex = calPosition(p1, p2, d_balance)
vertex_generated.append(vertex)
vertex_generated.append((points[-1][0], points[-1][1]))
# print vertex_generated
return vertex_generated
def addSheet(workbook, n):
sheet_name = "Sheet" + str(n)
worksheet = workbook.add_sheet(sheet_name)
worksheet.write(0, 0, "x")
worksheet.write(0, 1, "y")
return worksheet
def saveVertex(wooksheet, vertex_generated, vertex_num):
for i in range(vertex_num, vertex_num + len(vertex_generated)):
worksheet.write(i, 0, vertex_generated[i-vertex_num][0])
worksheet.write(i, 1, vertex_generated[i-vertex_num][1])
workbook = xlwt.Workbook(encoding='utf-8')
worksheet = addSheet(workbook, 1)
vertex_num = 1
sheet_index = 1
with arcpy.da.SearchCursor(fc_path, ("OID@", "SHAPE@")) as cursor:
for row in cursor:
print "------next row------"
for part in row[1]:
points = []
for point in part:
points.append((point.X, point.Y))
vertex_generated = splitLine(points, 10)
if (vertex_num + len(vertex_generated)) > 65500:
vertex_num = 1
sheet_index += 1
worksheet = addSheet(workbook, sheet_index)
saveVertex(worksheet, vertex_generated, vertex_num)
vertex_num += len(vertex_generated)
break
workbook.save('vertex_generated.xls')
print "------done------"