我意识到您正在要求使用QGIS方法,但是请允许我给出一个简单的答案:
roads = 'clipped roads' # roads layer
hexgrid = 'normal-hexgrid' # hex grid layer
sr = arcpy.Describe('roads').spatialReference # spatial reference
outlines = [] # final output lines
points = [] # participating grid vertices
vert_dict = {} # vertex dictionary
hex_dict = {} # grid dictionary
with arcpy.da.SearchCursor(roads,["SHAPE@","OID@"], spatial_reference=sr) as r_cursor: # loop through roads
for r_row in r_cursor:
with arcpy.da.SearchCursor(hexgrid,["SHAPE@","OID@"], spatial_reference=sr) as h_cursor: # loop through hex grid
for h_row in h_cursor:
if not r_row[0].disjoint(h_row[0]): # check if the shapes overlap
hex_verts = []
for part in h_row[0]:
for pnt in part:
hex_verts.append(pnt) # add grid vertices to list
int_pts = r_row[0].intersect(h_row[0],1) # find all intersection points between road and grid
hex_bnd = h_row[0].boundary() # convert grid to line
hex_dict[h_row[1]] = hex_bnd # add grid geometry to dictionary
for int_pt in int_pts: # loop through intersection points
near_dist = 1000 # arbitrary large number
int_pt = arcpy.PointGeometry(int_pt,sr)
for hex_vert in hex_verts: # loop through hex vertices
if int_pt.distanceTo(hex_vert) < near_dist: # find shortest distance between intersection point and grid vertex
near_vert = hex_vert # remember geometry
near_dist = int_pt.distanceTo(hex_vert) # remember distance
vert_dict.setdefault(h_row[1],[]).append(arcpy.PointGeometry(near_vert,sr)) # store geometry in dictionary
points.append(arcpy.PointGeometry(near_vert,sr)) # add to points list
for k,v in vert_dict.iteritems(): # loop through participating vertices
if len(v) < 2: # skip if there was only one vertex
continue
hex = hex_dict[k] # get hex grid geometry
best_path = hex # longest line possible is hex grid boundary
for part in hex:
for int_vert in v: # loop through participating vertices
for i,pnt in enumerate(part): # loop through hex grid vertices
if pnt.equals(int_vert): # find vertex index on hex grid corresponding to current point
start_i = i
if start_i == 6:
start_i = 0
for dir in [[0,6,1],[5,-1,-1]]: # going to loop once clockwise, once counter-clockwise
past_pts = 0 # keep track of number of passed participating vertices
cur_line_arr = arcpy.Array() # polyline coordinate holder
cur_line_arr.add(part[start_i]) # add starting vertex to growing polyline
for j in range(dir[0],dir[1],dir[2]): # loop through hex grid vertices
if past_pts < len(v): # only make polyline until all participating vertices have been visited
if dir[2] == 1: # hex grid vertex index bookkeeping
if start_i + j < 6:
index = start_i + j
else:
index = (start_i - 6) + j
else:
index = j - (5 - start_i)
if index < 0:
index += 6
cur_line_arr.add(part[index]) # add current vertex to growing polyline
for cur_pnt in v:
if part[index].equals(cur_pnt): # check if the current vertex is a participating vertex
past_pts += 1 # add to counter
if cur_line_arr.count > 1:
cur_line = arcpy.Polyline(cur_line_arr,sr)
if cur_line.length < best_path.length: # see if current polyline is shorter than any previous candidate
best_path = cur_line # if so, store polyline
outlines.append(best_path) # add best polyline to list
arcpy.CopyFeatures_management(outlines, r'in_memory\outlines') # write list
arcpy.CopyFeatures_management(points, r'in_memory\mypoints') # write points, if you want
笔记:
- 该脚本包含多个循环以及一个嵌套的游标。绝对有优化的空间。我花了几分钟查看了您的数据集,但更多功能会使问题更加复杂。