def buffer_search(o_res_xoff, o_res_yoff, water_ol_buf): global lake_ds, slope_ds, river_th, water_channel # 存储需要遍历的水体像元 water_points = [[o_res_xoff, o_res_yoff]] # 循环方式遍历水体像元 while len(water_points) > 0: current_point = water_points.pop() res_dir_array = cu.get_8_dir(current_point[0], current_point[1]) for index in range(0, 8, 1): # 水体数据中的索引 res_xoff = res_dir_array[index][0] res_yoff = res_dir_array[index][1] # 结果数据的该点索引 ol_point_off = cu.off_transform(res_xoff, res_yoff, lake_ds, slope_ds) re_xoff = ol_point_off[0] re_yoff = ol_point_off[1] # 若在数据内 if cu.in_data(re_xoff, re_yoff, slope_ds.RasterXSize, slope_ds.RasterYSize): # 判断是否记录在外边界数组 in_ol_array = ol_point_off in water_ol_buf # 判断是否在水体数据范围内 in_water_data = cu.in_data(res_xoff, res_yoff, lake_ds.RasterXSize, lake_ds.RasterYSize) # 若在水体数据中进一步判断是否为水体内像元 if in_water_data: data_value = cu.get_raster_int_value( lake_ds, res_xoff, res_yoff) not_in_water = data_value != water_value else: not_in_water = True # 若不是水体像元且未记录则记录,即记录新边界点 if not in_ol_array and not_in_water: # 添加缓冲区数组记录 water_ol_buf.append([re_xoff, re_yoff]) # 标记为水体外边界 cu.set_raster_int_value(slope_ds, re_xoff, re_yoff, water_buffer_value) # 判断是否在结果数据中记录水体 ol_data_value = cu.get_raster_int_value( slope_ds, re_xoff, re_yoff) recode_water = ol_data_value == water_value # 若是水体且未记录,则继续搜索 if not recode_water and not not_in_water: cu.set_raster_int_value(slope_ds, re_xoff, re_yoff, water_value) water_points.append([res_xoff, res_yoff])
def get_new_slope_surface(xoff, yoff, upstream_inflow, inflow_points): global acc_ds, river_th, slope_ds # 初始化搜索数组 search_array = [[xoff, yoff]] # 若继续搜索 while len(search_array) > 0: cell_xy = search_array.pop() neighbor_points = cu.get_8_dir(cell_xy[0], cell_xy[1]) # 遍历周边点 for point in neighbor_points: judge_in_data = cu.in_data(point[0], point[1], slope_ds.RasterXSize, slope_ds.RasterYSize) if judge_in_data: # 若该点为水体入流点且未记录合并 if point in upstream_inflow and point not in inflow_points: # 判断两点间是否穿插河道 # 两点若不存在中间点 if point[0] == cell_xy[0] or point[1] == cell_xy[1]: no_river = 1 else: # 判断中间点是否为河道 bd1_point = cu.off_transform(cell_xy[0], point[1], slope_ds, acc_ds) bd2_point = cu.off_transform(point[0], cell_xy[1], slope_ds, acc_ds) between_data_value1 = cu.get_raster_int_value(acc_ds, bd1_point[0], bd1_point[1]) between_data_value2 = cu.get_raster_int_value(acc_ds, bd2_point[0], bd2_point[1]) no_river = between_data_value1 < river_th and between_data_value2 < river_th # 若未穿插河道 if no_river: # 记录到当前坡面入流点集 inflow_points.append(point) # 以此点继续遍历 search_array.append(point) return inflow_points
def get_surface_route(surface_route_start): global acc_ds, dir_ds, route_ds, slope_ds, water_value, river_th, surface_route_value # 提取各水体的坡面流路 for route_start_point in surface_route_start: # 初始化流路追踪数组 judge_route = [route_start_point] while len(judge_route) > 0: current_point = judge_route.pop() xoff = current_point[0] yoff = current_point[1] # 获取此点其汇流累积量 acc_off = cu.off_transform(xoff, yoff, slope_ds, acc_ds) acc_value = cu.get_raster_float_value(acc_ds, acc_off[0], acc_off[1]) # 获取此点在结果数据的值 ol_value = cu.get_raster_int_value(slope_ds, xoff, yoff) # 若流向的点不为水体且不为河道则继续 if ol_value != water_value and acc_value < river_th: # 记录此点为坡面流路 cu.set_raster_int_value(route_ds, xoff, yoff, surface_route_value) # 获取此点流向 dir_value = cu.get_raster_int_value(dir_ds, xoff, yoff) # 获取其流向的点 to_point = cu.get_to_point(xoff, yoff, dir_value) if len(to_point) > 0: to_p_a_off = cu.off_transform(to_point[0], to_point[1], slope_ds, acc_ds) if cu.in_data(to_p_a_off[0], to_p_a_off[1], acc_ds.RasterXSize, acc_ds.RasterYSize): # 加入判断数组 judge_route.append(to_point)
def outline_upstream_search(xoff, yoff, water_buf, upstream_inflow): global dir_ds, slope_ds, water_value # 创建搜索数组 search_inflows = [[xoff, yoff]] # 开始搜索 while len(search_inflows) > 0: # 取出初始像元 cell_off = search_inflows.pop() xoff = cell_off[0] yoff = cell_off[1] # 搜索周边像元 ol_dir_array = cu.get_8_dir(xoff, yoff) for ol_n_cell in ol_dir_array: n_xoff = ol_n_cell[0] n_yoff = ol_n_cell[1] # 判断像元是否在数据集内且是否为有效流向 judge_in_data = cu.in_data(n_xoff, n_yoff, dir_ds.RasterXSize, dir_ds.RasterYSize) if judge_in_data: # 判断是否在水体内 ol_data = cu.get_raster_int_value(slope_ds, n_xoff, n_yoff) # 若不在水体则继续 if ol_data != water_value: dir_data_value = cu.get_raster_int_value(dir_ds, n_xoff, n_yoff) to_point = cu.get_to_point(n_xoff, n_yoff, dir_data_value) if len(to_point) != 0: # 若为上游点 if to_point[0] == xoff and to_point[1] == yoff: # 判断是否在外边界上,若是则记录 if ol_n_cell in water_buf: # 则记录为外边界上的上游坡面入流点 upstream_inflow.append([n_xoff, n_yoff]) # 继续遍历相邻像元 search_inflows.append(ol_n_cell)
def basin_divide(sub_basins_tif, boundary_geoj, trace_tif, acc_tif, dir_tif): # 获得多边形边界信息 polygons_array = sbu.get_polygon_points(boundary_geoj) # 找到主要边界所在多边形 main_polygon, main_index = sbu.get_main_polygon(polygons_array) # 判断是否需要更新岛到边界 if main_index['no_island'] == 1: polygon_pts = main_polygon else: # 更新岛到主要外边界 polygon_pts = sbu.update_island2boundary(polygons_array[main_index['polygon_index']]) trace_ds = gdal.Open(trace_tif) acc_ds = gdal.Open(acc_tif) dir_ds = gdal.Open(dir_tif) p_clockwise = sbu.is_clockwise(polygon_pts) # 边界为顺时针多边形 if p_clockwise: # 获取多边形顶点在栅格数据中的索引 p_offs = [] for point in polygon_pts: p_offs.append(cu.coord_to_off(point, trace_ds)) # 获取多边形其边对应的所有栅格索引的集合 polygon_ras_indexes = sbu.raster_index_on_polygon(p_offs) # 更新边界外部多边形内像元到内边界栅格集内 # 记录多个多边形连接处索引 joint_offs = [] if len(polygons_array) > 1: polygon_ras_indexes, joint_offs = sbu.update_outer2polygons(polygon_ras_indexes, trace_ds, polygons_array, main_index['polygon_index']) # 得到多边形边界内部邻接栅格像元的索引 inner_ras_indexes = sbu.inner_boundary_raster_indexes(polygon_ras_indexes, joint_offs) # 得到流域集合边界上出口栅格顺时针编号 outlets_order = outlets_index_order(inner_ras_indexes, trace_ds) # 以四个大流域为界将流域出口分组 outlet_groups = divide_outlet_to_group(outlets_order, acc_ds) file_format = "GTiff" driver = gdal.GetDriverByName(file_format) sub_ds = driver.Create(sub_basins_tif, trace_ds.RasterXSize, trace_ds.RasterYSize, 1, gdal.GDT_Int16, options=['COMPRESS=DEFLATE']) sub_ds.SetGeoTransform(trace_ds.GetGeoTransform()) sub_ds.SetProjection(trace_ds.GetProjection()) sub_ds.GetRasterBand(1).SetNoDataValue(-1) for i in range(len(outlet_groups)): outlet_group = outlet_groups[i] for outlet in outlet_group: x_off = outlet[0] y_off = outlet[1] if cu.in_data(x_off, y_off, sub_ds.RasterXSize, sub_ds.RasterYSize): outlet_basins(outlet, sub_ds, i + 1, dir_ds) else: print('No support anticlockwise!') trace_ds = None sub_ds = None acc_ds = None dir_ds = None
def outlet_basins(outlet, result_ds, s_id, dir_ds): # 创建追踪数组 trace_array = [outlet] # 若需要继续追踪 while len(trace_array) > 0: # 取出当前像元 cur_cell = trace_array.pop() cur_x = cur_cell[0] cur_y = cur_cell[1] # 对当前像元赋值 cu.set_raster_int_value(result_ds, cur_x, cur_y, s_id) # 获取周边像元索引 n_8_cells = cu.get_8_dir(cur_x, cur_y) # 遍历8个像元 for n_cell in n_8_cells: n_x = n_cell[0] n_y = n_cell[1] # 若在数据范围内 if cu.in_data(n_x, n_y, dir_ds.RasterXSize, dir_ds.RasterYSize): # 获得当前点流向值 dir_value = cu.get_raster_int_value(dir_ds, n_x, n_y) # 获得下游点索引 to_point = cu.get_to_point_128(n_x, n_y, dir_value) # 若为当前点的上游点 if to_point == cur_cell: # 将此像元加入到流域追踪数组 trace_array.append(n_cell)
def surface_merge(upstream_inflow, new_slope_surface_id): global slope_ds, dir_ds, water_buffer_value, water_value # 定义合并后的坡面分组 slope_surface_unit = [] # 遍历上游流入点对坡面与水体相交处的入流口分组 for upstream_point in upstream_inflow: # 判断坡面入流点已参与合并 not_in_unit = 1 for index in range(0, len(slope_surface_unit), 1): if upstream_point in slope_surface_unit[index]: not_in_unit = 0 break # 若坡面入流点未参与合并 if not_in_unit: # 创建新坡面集合并添加新坡面的首个水体入流点 slope_surface = [upstream_point] # 获取新坡面集合的入流点集 slope_surface = get_new_slope_surface(upstream_point[0], upstream_point[1], upstream_inflow, slope_surface) # 将新坡面放入合并后的坡面集合中 slope_surface_unit.append(slope_surface) # 获取合并后新坡面的id new_slope_surface_id += 1 # 以各合并坡面的入口点集开始合并坡面 for index in range(0, len(slope_surface_unit), 1): # print(slope_surface_unit[index]) # 获取合并后新坡面与水体的交界点 s_s_inflows = slope_surface_unit[index] for inflow_point in s_s_inflows: # 初始化需要更新的像元集 to_update_points = [inflow_point] # 循环直到待更新数组为空 while len(to_update_points) > 0: # 取出第一个点 to_update_point = to_update_points.pop() # 更新此点id cu.set_raster_int_value(slope_ds, to_update_point[0], to_update_point[1], new_slope_surface_id) # 获取此点周边需要更新的像元集 # 获取邻近像元 neighbor_points = cu.get_8_dir(to_update_point[0], to_update_point[1]) # 判断各像元是否需要更新 for point in neighbor_points: point_x = point[0] point_y = point[1] judge_in_data = cu.in_data(point_x, point_y, slope_ds.RasterXSize, slope_ds.RasterYSize) if judge_in_data: # 若不为水体则继续 ol_data = cu.get_raster_int_value(slope_ds, point_x, point_y) if ol_data != water_value: # 若是当前点的上游点 dir_point = cu.off_transform(point_x, point_y, slope_ds, dir_ds) dir_value = cu.get_raster_int_value(dir_ds, dir_point[0], dir_point[1]) to_point = cu.get_to_point(point_x, point_y, dir_value) if to_point == to_update_point: # 加入待更新数组 to_update_points.append(point) return new_slope_surface_id
def get_trace_from_record(refer_tif, seaside_txt, final_txt, trace_tif): ref_ds = gdal.Open(refer_tif) print("Create Trace file...") file_format = "GTiff" driver = gdal.GetDriverByName(file_format) full_geotransform = ref_ds.GetGeoTransform() trace_ds = driver.Create(trace_tif, ref_ds.RasterXSize, ref_ds.RasterYSize, 1, gdal.GDT_Byte) trace_ds.SetGeoTransform(full_geotransform) trace_ds.SetProjection(ref_ds.GetProjection()) trace_ds.GetRasterBand(1).SetNoDataValue(0) # 将内流区域终点更新到河流数据 print("Add Final to Trace file...") with open(final_txt, 'r') as final_file: for line in final_file.readlines(): final_info_str = line.strip('\n') final_info = final_info_str.split(',') # 将final像元的x,y索引 f_x_coord = float(final_info[0]) f_y_coord = float(final_info[1]) off_xy = cu.coord_to_off([f_x_coord, f_y_coord], trace_ds) if cu.in_data(off_xy[0], off_xy[1], trace_ds.RasterXSize, trace_ds.RasterYSize): cu.set_raster_int_value(trace_ds, off_xy[0], off_xy[1], 1) # 将内流区域终点更新到河流数据 print("Add Seaside to Trace file...") with open(seaside_txt, 'r') as final_file: for line in final_file.readlines(): final_info_str = line.strip('\n') final_info = final_info_str.split(',') # 将seaside像元的x,y索引 f_x_coord = float(final_info[0]) f_y_coord = float(final_info[1]) off_xy = cu.coord_to_off([f_x_coord, f_y_coord], trace_ds) if cu.in_data(off_xy[0], off_xy[1], trace_ds.RasterXSize, trace_ds.RasterYSize): cu.set_raster_int_value(trace_ds, off_xy[0], off_xy[1], 1) print('over.') ref_ds = None trace_ds = None
def add_final_to_river(dir_tif, final_points_txt, river_tif, acc_tif, river_th=None): dir_ds = gdal.Open(dir_tif, 1) rt_ds = gdal.Open(river_tif, 1) acc_ds = gdal.Open(acc_tif) # 将内流区域终点更新到河流数据 with open(final_points_txt, 'r') as final_file: for line in final_file.readlines(): final_info_str = line.strip('\n') final_info = final_info_str.split(',') # 将final像元的x,y索引 f_x_coord = float(final_info[0]) f_y_coord = float(final_info[1]) final_off = cu.coord_to_off([f_x_coord, f_y_coord], rt_ds) final_xoff = final_off[0] final_yoff = final_off[1] # 得到在河流中对应的索引 r_off = cu.off_transform(final_xoff, final_yoff, dir_ds, rt_ds) # 若在数据内 if cu.in_data(r_off[0], r_off[1], rt_ds.RasterXSize, rt_ds.RasterYSize): # 寻找内流终点周边最小汇流累积像元(最后形成虚拟河系) ne_cells = cu.get_8_dir(final_xoff, final_yoff) min_acc_point = [] min_acc = cu.get_raster_float_value(acc_ds, final_xoff, final_yoff) for point in ne_cells: acc_value = cu.get_raster_float_value( acc_ds, point[0], point[1]) if acc_value < min_acc: min_acc = acc_value min_acc_point = point # 若最小累积量像元不成为河系 if river_th is None or min_acc < river_th: # 则赋值内流终点流向该方向 dir_value = 1 if river_th is not None: dir_value = cu.dir_between_points( [final_xoff, final_yoff], min_acc_point) cu.set_raster_int_value(dir_ds, final_xoff, final_yoff, dir_value) # 记录Final point到河流 cu.set_raster_int_value(rt_ds, r_off[0], r_off[1], 1)
def get_no_inflow_cells(dir_tif, no_inflow_tif): dir_ds = gdal.Open(dir_tif) # 创建无流入点数据 print("Create No inflow file...") file_format = "GTiff" driver = gdal.GetDriverByName(file_format) full_geotransform = dir_ds.GetGeoTransform() ni_ds = driver.Create(no_inflow_tif, dir_ds.RasterXSize, dir_ds.RasterYSize, 1, gdal.GDT_Int32, options=['COMPRESS=DEFLATE']) ni_ds.SetGeoTransform(full_geotransform) ni_ds.SetProjection(dir_ds.GetProjection()) ni_ds.GetRasterBand(1).SetNoDataValue(0) # 遍历基础数据记录无流入点 print("Get No Inflow Data...") for i in range(dir_ds.RasterYSize): for j in range(dir_ds.RasterXSize): c_point = [j, i] # 邻近像元索引 n_points = cu.get_8_dir(c_point[0], c_point[1]) # 初始化流入标记 inflow_flag = 0 for n_point in n_points: # 判断是否在数据内 in_data = cu.in_data(n_point[0], n_point[1], dir_ds.RasterXSize, dir_ds.RasterYSize) if in_data: # 判断是否流向原像元点 n_dir = cu.get_raster_int_value(dir_ds, n_point[0], n_point[1]) to_point = cu.get_to_point(n_point[0], n_point[1], n_dir) if to_point == c_point: inflow_flag = 1 break # 若无流入则记录 if not inflow_flag: cu.set_raster_int_value(ni_ds, c_point[0], c_point[1], 1)
def recode_from_river(watershed_id, river_x, river_y, watershed_tif_path, dir_tif_path, water_tif_path, rivers_index): global water_value # 创建数据集 watershed_ds = gdal.OpenEx(watershed_tif_path, 1) dir_ds = gdal.Open(dir_tif_path) water_ds = gdal.Open(water_tif_path) # 初始化需要赋值的像元集合 update_cells = [[river_x, river_y]] # 更新区域内像元值 # print(">>> update cell:", end='') while len(update_cells) > 0: # 取出要更新的像元索引 update_cell = update_cells.pop() # print(update_cell, end='') # 更新像元值 cu.set_raster_int_value(watershed_ds, update_cell[0], update_cell[1], watershed_id) # print('update: ', update_cell, '->', watershed_id) # 得到邻近像元集合 neighbor_cells = cu.get_8_dir(update_cell[0], update_cell[1]) # 搜索上游像元 for neighbor_cell in neighbor_cells: n_x = neighbor_cell[0] n_y = neighbor_cell[1] # 判断邻近点是否在数据内 if cu.in_data(n_x, n_y, watershed_ds.RasterXSize, watershed_ds.RasterYSize): # 若不为河段并不为湖泊/水库(即若为子流域) water_off = cu.off_transform(n_x, n_y, watershed_ds, water_ds) in_water = cu.is_water_cell(water_ds, water_off[0], water_off[1], water_value) if neighbor_cell not in rivers_index and not in_water: dir_value = cu.get_raster_int_value(dir_ds, n_x, n_y) to_point = cu.get_to_point(n_x, n_y, dir_value) # 若为上游点 if to_point == update_cell: # 加入更新数组 update_cells.append(neighbor_cell) watershed_ds = None dir_ds = None
def get_slope_surface(lake_tif_path, dir_tif_path, acc_tif_path, slope_tif_path, route_tif_path, river_threshold, no_data=None): print("Extract Start") global lake_ds, dir_ds, acc_ds, slope_ds, route_ds, river_th, water_ol_bufs, no_data_value river_th = river_threshold lake_ds = gdal.Open(lake_tif_path) dir_ds = gdal.Open(dir_tif_path) acc_ds = gdal.Open(acc_tif_path) if no_data is not None: no_data_value = no_data else: no_data_value = int(lake_ds.GetRasterBand(1).GetNoDataValue()) dir_geotransform = dir_ds.GetGeoTransform() full_geotransform = dir_geotransform # 创建坡面提取结果数据 file_format = "GTiff" driver = gdal.GetDriverByName(file_format) slope_ds = driver.Create(slope_tif_path, dir_ds.RasterXSize, dir_ds.RasterYSize, 1, gdal.GDT_Int32, options=['COMPRESS=DEFLATE']) slope_ds.SetGeoTransform(full_geotransform) slope_ds.SetProjection(dir_ds.GetProjection()) slope_ds.GetRasterBand(1).SetNoDataValue(no_data_value) # 创建坡面流路结果数据 route_ds = driver.Create(route_tif_path, dir_ds.RasterXSize, dir_ds.RasterYSize, 1, gdal.GDT_Int16, options=['COMPRESS=DEFLATE']) route_ds.SetGeoTransform(full_geotransform) route_ds.SetProjection(dir_ds.GetProjection()) route_ds.GetRasterBand(1).SetNoDataValue(no_data_value) print("Get lakes' outline...") for i in range(lake_ds.RasterYSize): for j in range(lake_ds.RasterXSize): # 获取水体数据某点的值 scan_value = cu.get_raster_int_value(lake_ds, j, i) # 若是水体内的像元 if scan_value == water_value: # 计算水体数据的x,y坐标 off_point = cu.off_transform(j, i, lake_ds, slope_ds) re_xoff = off_point[0] re_yoff = off_point[1] # 若在数据集内 if cu.in_data(re_xoff, re_yoff, slope_ds.RasterXSize, slope_ds.RasterYSize): # 获取结果数据的值 re_data_value = cu.get_raster_int_value(slope_ds, re_xoff, re_yoff) # 若未记录则继续 if re_data_value != water_value: # 新建数组用于记录此水体外边界 water_ol_buf = [] # 结果数据记录水体 cu.set_raster_int_value(slope_ds, re_xoff, re_yoff, water_value) # 使用3*3区域生成水体外包围像元集 buffer_search(j, i, water_ol_buf) # 若有新的水体外边界则记录到集合 if len(water_ol_buf) > 0: # 将此水体的外边界记录到集合中 water_ol_bufs.append(water_ol_buf) print("Sort the extraction of slope surface...") # 对水体的坡面提取排序(由小到大) water_ol_bufs_ordered = [] surface_route_start = water_order(water_ol_bufs, water_ol_bufs_ordered) print("Search slope surface inflow points...") # 搜索水体外边界上坡面像元集合 # 坡面id初始化 # 上游流入点的集合 upstream_inflows = [] for water_ol_buf in water_ol_bufs_ordered: slope_surface_inflows(water_ol_buf, upstream_inflows) print("Merge lakes' slope surface...") # 合并坡面入流口相邻的坡面 s_new_id = 0 for upstream_inflow in upstream_inflows: s_new_id = surface_merge(upstream_inflow, s_new_id) print("Record slope surface route...") # 提取坡面流路 get_surface_route(surface_route_start) print("Clear marks...") # 清除边界线标记 for water_ol_buf in water_ol_bufs_ordered: clear_buffer(water_ol_buf) lake_ds = None dir_ds = None acc_ds = None slope_ds = None route_ds = None print("Extract End")
def watershed_erase_area(dem_tif_path, dir_tif_path, acc_tif_path, stream_tif_path, water_s_s_tif_path, result_path): print("Erasing Mask Area from Dataset") # 获取数据集 dem_old_ds = gdal.Open(dem_tif_path) dir_old_ds = gdal.Open(dir_tif_path) acc_old_ds = gdal.Open(acc_tif_path) stream_old_ds = gdal.Open(stream_tif_path) mask_ds = gdal.Open(water_s_s_tif_path) # 获取无数据标识 dem_no_data = get_nodata_value(dem_old_ds) dir_no_data = get_nodata_value(dir_old_ds) acc_no_data = get_nodata_value(acc_old_ds) stream_no_data = get_nodata_value(stream_old_ds) mask_no_data = get_nodata_value(mask_ds) # 新数据路径 dem_new_path = result_path + "/dem_erase.tif" dir_new_path = result_path + "/dir_erase.tif" acc_new_path = result_path + "/acc_erase.tif" stream_new_path = result_path + "/stream_erase.tif" # 创建结果数据 file_format = "GTiff" driver = gdal.GetDriverByName(file_format) dem_new_ds = driver.CreateCopy(dem_new_path, dem_old_ds) dir_new_ds = driver.CreateCopy(dir_new_path, dir_old_ds) acc_new_ds = driver.CreateCopy(acc_new_path, acc_old_ds) stream_new_ds = driver.CreateCopy(stream_new_path, stream_old_ds) # 剔除掩膜区域处理 for j in range(mask_ds.RasterYSize): for i in range(mask_ds.RasterXSize): mask_data = cu.get_raster_int_value(mask_ds, i, j) if mask_data != mask_no_data: # 处理DEM result_point = cu.off_transform(i, j, mask_ds, dem_new_ds) if cu.in_data(result_point[0], result_point[1], dem_new_ds.RasterXSize, dem_new_ds.RasterYSize): cu.set_raster_float_value(dem_new_ds, result_point[0], result_point[1], dem_no_data) # 处理流向 result_point = cu.off_transform(i, j, mask_ds, dir_new_ds) if cu.in_data(result_point[0], result_point[1], dir_new_ds.RasterXSize, dir_new_ds.RasterYSize): cu.set_raster_int_value(dir_new_ds, result_point[0], result_point[1], int(dir_no_data)) # 处理汇流累积量 result_point = cu.off_transform(i, j, mask_ds, acc_new_ds) if cu.in_data(result_point[0], result_point[1], acc_new_ds.RasterXSize, acc_new_ds.RasterYSize): cu.set_raster_float_value(acc_new_ds, result_point[0], result_point[1], acc_no_data) # 处理河网 result_point = cu.off_transform(i, j, mask_ds, stream_new_ds) if cu.in_data(result_point[0], result_point[1], stream_new_ds.RasterXSize, stream_new_ds.RasterYSize): cu.set_raster_int_value(stream_new_ds, result_point[0], result_point[1], int(stream_no_data)) dem_old_ds = None dir_old_ds = None acc_old_ds = None stream_old_ds = None dem_new_ds = None dir_new_ds = None acc_new_ds = None stream_new_ds = None mask_ds = None return [dem_new_path, dir_new_path, acc_new_path, stream_new_path]
def basin_divide(sub_basins_tif, boundary_geoj, trace_tif, acc_tif, dir_tif): # 获得多边形边界信息 polygons_array = sbu.get_polygon_points(boundary_geoj) # 找到主要边界所在多边形 main_polygon, main_index = sbu.get_main_polygon(polygons_array) # 判断是否需要更新岛到边界 if main_index['no_island'] == 1: polygon_pts = main_polygon else: # 更新岛到主要外边界 polygon_pts = sbu.update_island2boundary( polygons_array[main_index['polygon_index']]) trace_ds = gdal.Open(trace_tif) acc_ds = gdal.Open(acc_tif) dir_ds = gdal.Open(dir_tif) p_clockwise = sbu.is_clockwise(polygon_pts) # 边界为顺时针多边形 if p_clockwise: # 获取多边形顶点在栅格数据中的索引 p_offs = [] for point in polygon_pts: p_offs.append(cu.coord_to_off(point, trace_ds)) # 获取多边形其边对应的所有栅格索引的集合 polygon_ras_indexes = sbu.raster_index_on_polygon(p_offs) # 更新边界外部多边形内像元到内边界栅格集内 # 记录多个多边形连接处索引 joint_offs = [] if len(polygons_array) > 1: polygon_ras_indexes, joint_offs = sbu.update_outer2polygons( polygon_ras_indexes, trace_ds, polygons_array, main_index['polygon_index']) # 得到多边形边界内部邻接栅格像元的索引 inner_ras_indexes = sbu.inner_boundary_raster_indexes( polygon_ras_indexes, joint_offs) # # 输出到tif # temp_path = r'G:\Graduation\Program\Data\51\nested\5\56\566\process\boundary.tif' # file_format = "GTiff" # driver = gdal.GetDriverByName(file_format) # temp_ds = driver.Create(temp_path, trace_ds.RasterXSize, trace_ds.RasterYSize, 1, gdal.GDT_Float32, options=['COMPRESS=DEFLATE']) # temp_ds.SetGeoTransform(trace_ds.GetGeoTransform()) # temp_ds.SetProjection(trace_ds.GetProjection()) # temp_ds.GetRasterBand(1).SetNoDataValue(-1) # for off_index in range(len(inner_ras_indexes)): # off = inner_ras_indexes[off_index] # cu.set_raster_float_value(temp_ds, off[0], off[1], off_index*0.001) # temp_ds = None # 得到流域集合边界上出口栅格顺时针编号 outlets_order = outlets_index_order(inner_ras_indexes, trace_ds) # # 输出到tif # temp_path = r'G:\Graduation\Program\Data\51\nested\5\56\566\process\outlet_order.tif' # file_format = "GTiff" # driver = gdal.GetDriverByName(file_format) # temp_ds = driver.Create(temp_path, trace_ds.RasterXSize, trace_ds.RasterYSize, 1, gdal.GDT_Float32, options=['COMPRESS=DEFLATE']) # temp_ds.SetGeoTransform(trace_ds.GetGeoTransform()) # temp_ds.SetProjection(trace_ds.GetProjection()) # temp_ds.GetRasterBand(1).SetNoDataValue(-1) # for off_index in range(len(outlets_order)): # off = outlets_order[off_index] # cu.set_raster_float_value(temp_ds, off[0], off[1], off_index*0.001) # temp_ds = None # 得到排序好的出口索引在acc数据中的索引 outlets_order_in_acc = [] for outlet in outlets_order: coord = cu.off_to_coord(outlet, trace_ds) outlets_order_in_acc.append(cu.coord_to_off(coord, acc_ds)) # 以四个大流域为界将流域出口分组 outlet_groups = divide_outlet_to_group(outlets_order_in_acc, acc_ds) file_format = "GTiff" driver = gdal.GetDriverByName(file_format) sub_ds = driver.Create(sub_basins_tif, acc_ds.RasterXSize, acc_ds.RasterYSize, 1, gdal.GDT_Int16, options=['COMPRESS=DEFLATE']) sub_ds.SetGeoTransform(acc_ds.GetGeoTransform()) sub_ds.SetProjection(acc_ds.GetProjection()) sub_ds.GetRasterBand(1).SetNoDataValue(-1) for i in range(len(outlet_groups)): outlet_group = outlet_groups[i] for outlet in outlet_group: x_off = outlet[0] y_off = outlet[1] if cu.in_data(x_off, y_off, sub_ds.RasterXSize, sub_ds.RasterYSize): outlet_basins(outlet, sub_ds, i + 1, dir_ds) else: print('No support anticlockwise!') trace_ds = None sub_ds = None acc_ds = None dir_ds = None
def get_trace_points(dir_tif, flag_tif, trace_tif, seaside_txt=None, final_txt=None): coastline_value = 0 final_value = -1 dir_ds = gdal.Open(dir_tif) f_ds = gdal.Open(flag_tif) # 创建trace start数据 print("Create Trace file...") file_format = "GTiff" driver = gdal.GetDriverByName(file_format) full_geotransform = dir_ds.GetGeoTransform() trace_ds = driver.Create(trace_tif, dir_ds.RasterXSize, dir_ds.RasterYSize, 1, gdal.GDT_Byte, options=['COMPRESS=DEFLATE']) trace_ds.SetGeoTransform(full_geotransform) trace_ds.SetProjection(dir_ds.GetProjection()) trace_ds.GetRasterBand(1).SetNoDataValue(0) # 创建记录文件 seaside_flag = 0 seaside_f = None if seaside_txt is not None: print("Record Final Points.") seaside_flag = 1 if os.path.exists(seaside_txt): os.remove(seaside_txt) if seaside_flag: seaside_f = open(seaside_txt, "a") final_flag = 0 final_f = None if final_txt is not None: print("Record Final Points.") final_flag = 1 if os.path.exists(final_txt): os.remove(final_txt) if final_flag: final_f = open(final_txt, "a") # 遍历基础数据记录seaside print("Get Trace Data...") for i in range(f_ds.RasterYSize): for j in range(f_ds.RasterXSize): # 获取流向的值 flag_value = cu.get_raster_int_value(f_ds, j, i) # 如果是coastline if flag_value == coastline_value: # 获取周边像元索引 neibor_cells = cu.get_8_dir(j, i) # 遍历 for n_cell in neibor_cells: # 判断是否在数据内 in_data = cu.in_data(n_cell[0], n_cell[1], dir_ds.RasterXSize, dir_ds.RasterYSize) # 若在数据内 if in_data: # 获取流向值 dir_value = cu.get_raster_int_value(dir_ds, n_cell[0], n_cell[1]) # 获取流向的像元索引 n_to_point = cu.get_to_point(n_cell[0], n_cell[1], dir_value) # 若为当前上游像元 if n_to_point == [j, i]: # 记录为seaside cu.set_raster_int_value(trace_ds, n_cell[0], n_cell[1], 1) # 记录到文件 if seaside_flag: # 获得栅格像元左上角坐标 seaside_record_item = cu.off_to_coord([j, i], f_ds) seaside_record_str = ','.join(str(k) for k in seaside_record_item) seaside_f.write(seaside_record_str + '\n') # 如果是final point elif flag_value == final_value: # 记录为final points cu.set_raster_int_value(trace_ds, j, i, 1) # 记录到文件 if final_flag: final_record_item = cu.off_to_coord([j, i], f_ds) final_record_str = ','.join(str(k) for k in final_record_item) final_f.write(final_record_str + '\n') dir_ds = None f_ds = None trace_ds = None seaside_f = None final_f = None