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 down_point_coord(b_point, dir_index): current_dir_path = find_data_by_point(b_point, dir_index) cu_dir_ds = gdal.Open(current_dir_path) dir_off = cu.coord_to_off(b_point, cu_dir_ds) dir_value = cu.get_raster_int_value(cu_dir_ds, dir_off[0], dir_off[1]) to_off = cu.get_to_point(dir_off[0], dir_off[1], dir_value) to_coord = cu.off_to_coord(to_off, cu_dir_ds) cu_dir_ds = None return to_coord
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 basin_spill(boundary_geoj, dem_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']]) dem_ds = gdal.Open(dem_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, dem_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, dem_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\42\boundary.tif' # file_format = "GTiff" # driver = gdal.GetDriverByName(file_format) # temp_ds = driver.Create(temp_path, dem_ds.RasterXSize, dem_ds.RasterYSize, 1, gdal.GDT_Int16, options=['COMPRESS=DEFLATE']) # temp_ds.SetGeoTransform(dem_ds.GetGeoTransform()) # temp_ds.SetProjection(dem_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_int_value(temp_ds, off[0], off[1], off_index) # temp_ds = None # 得到流域内边界最低点及出流方向 spill_point, spill_dir, reception_pt = spill_point_dir(inner_ras_indexes, dem_ds) # 得到接受点的坐标 reception_pt_coord = cu.off_to_coord(reception_pt, dem_ds) return spill_point, spill_dir, reception_pt_coord else: print('No support anticlockwise!') dem_ds = None return [], 0, []
def update_outer2polygons(polygon_ras_indexes, refer_ds, polygons_array, main_p_index): joint_offs = [] for polygon_index in range(len(polygons_array)): # 遍历其他多边形 if polygon_index != main_p_index: # 得到多边形 polygon = polygons_array[polygon_index] # 若不存在岛 if len(polygon) == 1: polygon = polygon[0] # 若为单个像元 if len(polygon) == 5: temp_list = polygon[:len(polygon) - 1] for index in range(len(temp_list)): polygon_pt = temp_list[index] pt_off = cu.coord_to_off(polygon_pt, refer_ds) # 若相邻 if pt_off in polygon_ras_indexes: # 记录相邻点索引 joint_offs.append(pt_off) # 获取插入到边界点集的位置 in_main_index = polygon_ras_indexes.index(pt_off) # 初始化插入数组 join_off = [] for n_index in range(index, len(temp_list)): pt = temp_list[n_index] off = cu.coord_to_off(pt, refer_ds) join_off.append(off) for n_index in range(0, index): pt = temp_list[n_index] off = cu.coord_to_off(pt, refer_ds) join_off.append(off) join_off.reverse() for off in join_off: polygon_ras_indexes.insert(in_main_index, off) break else: print('暂不支持较大多边形') else: print('暂不支持含岛多边形') return polygon_ras_indexes, joint_offs
def update_acc_by_coord(point, acc_index, acc_value): current_acc_path = find_data_by_point(point, acc_index) cu_acc_ds = gdal.Open(current_acc_path, 1) cu_off = cu.coord_to_off(point, cu_acc_ds) cu.set_raster_float_value(cu_acc_ds, cu_off[0], cu_off[1], acc_value) cu_acc_ds = None # 另行记录更新的像元 global update_index update_index += 1 # check_off = cu.coord_to_off(point, dataset_ol) # cu.set_raster_float_value(dataset_ol, check_off[0], check_off[1], acc_value) print("\r", point, "->", acc_value, " Updated Num: ", update_index, end="")
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 able_update_acc(b_point, x_size, y_size, acc_index, dir_index): global nc # 获取acc整体数据边界 total_lt = list(acc_index.values())[0][0][:] total_rb = list(acc_index.values())[0][0][:] for value in acc_index.values(): if total_lt[0] >= value[0][0]: total_lt[0] = value[0][0] if total_lt[1] <= value[0][1]: total_lt[1] = value[0][1] if total_rb[0] <= value[1][0]: total_rb[0] = value[1][0] if total_rb[1] >= value[1][1]: total_rb[1] = value[1][1] # 初始化上游像元汇流累积量(初始化为0) up_cells_acc = 0 # 初始化标记存在上游像元(初始化为不存在) up_cell_flag = 0 # 初始化标记存在上游像元acc暂为nodata(初始化为存在nodata上游点) up_nodata_flag = 0 # 获取周边像元坐标(左上角)从邻近像元搜索 n_cells = cu.get_8_dir_coord(b_point[0], b_point[1], x_size, y_size) for n_cell in n_cells: # 得到所处数据块 acc_path = find_data_by_point(n_cell, acc_index) dir_path = find_data_by_point(n_cell, dir_index) if acc_path != "" and dir_path != "": # 判断是否为上游点 dir_ds = gdal.Open(dir_path) # 根据坐标转为索引 n_off = cu.coord_to_off(n_cell, dir_ds) # 获得此处流向值 dir_value = cu.get_raster_int_value(dir_ds, n_off[0], n_off[1]) # 获得下游像元索引 d_off = cu.get_to_point(n_off[0], n_off[1], dir_value) # 若为有下游像元 if d_off: # 获取该下游像元的坐标 d_coord = cu.off_to_coord(d_off, dir_ds) # 若该下游像元坐标与当前坐标相同则此邻近像元为上游像元 if d_coord == b_point: up_cell_flag = 1 # 获取此上游像元处的汇流累积量值 acc_ds = gdal.Open(acc_path) n_acc_off = cu.coord_to_off(n_cell, acc_ds) n_acc = cu.get_raster_float_value(acc_ds, n_acc_off[0], n_acc_off[1]) # 若此acc值为nodata则标记存在上游像元acc暂为nodata if int(n_acc) <= 0: up_nodata_flag = 1 break # 否则记录当前值到总上游累积量 else: up_cells_acc += n_acc acc_ds = None dir_ds = None # 若存在上游像元 if up_cell_flag: # 若上游像元均有有效acc值 if up_nodata_flag == 0: # 更新上游acc总值和自身累积量值到当前像元 current_acc = up_cells_acc + 1.0 return current_acc # 存在上游像元暂为nodata else: return 0 # 若不存在上游像元 else: # 若考虑边界污染 if nc: # 若在边界上 if in_edge(b_point, total_lt, total_rb): return 0 else: # 否则作为汇流起始点 return 1.0 # 若不考虑边界污染 else: return 1.0
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