Example #1
0
def record_rivers(work_path, river_tif_path, acc_tif_path):
    # 创建结果数据文件夹
    if not os.path.exists(work_path):
        os.makedirs(work_path)

    # 创建数据集
    river_ds = gdal.Open(river_tif_path)
    acc_ds = gdal.Open(acc_tif_path)

    # 创建河流记录文件
    river_record_txt = work_path + "/river_record.txt"
    if os.path.exists(river_record_txt):
        os.remove(river_record_txt)

    print("Recording rivers...")

    # 记录河流信息到文件
    with open(river_record_txt, 'a') as river_f:
        for i in range(river_ds.RasterYSize):
            for j in range(river_ds.RasterXSize):
                # 获取river中该点的值
                river_value = cu.get_raster_int_value(river_ds, j, i)
                # 判断是否为河流
                if river_value == 1:
                    # 需要记录的河系信息:x索引,y索引,汇流累积量
                    river_cell_acc = cu.get_raster_float_value(acc_ds, j, i)
                    river_record_item = [j, i, river_cell_acc]
                    # 记录到文件中
                    river_record_str = ','.join(str(k) for k in river_record_item)
                    river_f.write(river_record_str + '\n')

    print("File write over.")
Example #2
0
def record_temp_nodata(acc_paths, dir_paths):
    # 初始化有效nodata的坐标索引集合
    temp_nodata = []
    # 遍历数据块
    for index in range(0, len(acc_paths)):
        acc_tif = acc_paths[index]
        dir_tif = dir_paths[index]
        acc_ds = gdal.Open(acc_tif)
        dir_ds = gdal.Open(dir_tif)
        acc_nodata = acc_ds.GetRasterBand(1).GetNoDataValue()
        # # 遍历数据块的像元
        for y in range(acc_ds.RasterYSize):
            for x in range(acc_ds.RasterXSize):
                # 判断是否为nodata
                acc_value = cu.get_raster_float_value(acc_ds, x, y)
                if acc_value == acc_nodata:
                    # 判断是否为有效nodata
                    dir_off = cu.off_transform(x, y, acc_ds, dir_ds)
                    dir_value = cu.get_raster_int_value(
                        dir_ds, dir_off[0], dir_off[1])
                    # 若是有效nodata则记录其左上角坐标索引
                    if dir_value in [1, 2, 3, 4, 5, 6, 7, 8]:
                        # 当前像元的左上角坐标
                        transform = acc_ds.GetGeoTransform()
                        xy_current = [
                            transform[0] + x * transform[1],
                            transform[3] + y * transform[5]
                        ]
                        # 记录到数组
                        temp_nodata.append(xy_current)
        acc_ds = None
        dir_ds = None
    return temp_nodata
def spill_point_dir(inner_ras_indexes, dem_ds):
    # 内边界的高程
    inner_dem = []
    for ras_index in inner_ras_indexes:
        dem_value = cu.get_raster_float_value(dem_ds, ras_index[0], ras_index[1])
        inner_dem.append(dem_value)
    # 获得最低位置的索引
    spill_pt_index = list(map(inner_dem.index, heapq.nsmallest(1, inner_dem)))[0]
    spill_pt = inner_ras_indexes[spill_pt_index]
    # 获得溢出方向
    spill_dir = get_spill_dir(inner_ras_indexes, spill_pt_index)
    # 得到接收点索引
    reception_pt = cu.get_to_point(spill_pt[0], spill_pt[1], spill_dir)

    # # 输出到tif
    # temp_path = r'G:\Graduation\Program\Data\41\endorheic_area0\outlet_dir.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)
    # cu.set_raster_int_value(temp_ds, spill_pt[0], spill_pt[1], spill_dir)
    # temp_ds = None

    return spill_pt, spill_dir, reception_pt
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 slope_surface_inflows(water_buf, upstream_inflows):
    global slope_ds, acc_ds, water_buffer_value, river_th
    # 定义非河道出入流处的外边界点集
    upstream_inflow = []
    # 遍历水体的外边线更新由边界线直接流入水体的部分
    for x_y_couple in water_buf:
        xoff = x_y_couple[0]
        yoff = x_y_couple[1]
        # 判断是否为边界上的非河道出入流处且未被标记
        ol_data_value = cu.get_raster_int_value(slope_ds, xoff, yoff)
        acc_off = cu.off_transform(xoff, yoff, slope_ds, acc_ds)
        acc_data_value = cu.get_raster_float_value(acc_ds, acc_off[0], acc_off[1])
        not_is_channel = ol_data_value == water_buffer_value and acc_data_value < river_th
        # 若为非河道出入流处
        if not_is_channel:
            # 判断是否指向水体
            to_point_data = get_to_point_ol_data(xoff, yoff)
            judge_to_water = to_point_data == water_value
            # 若流向水体
            if judge_to_water:
                # 记录为水体外边界上的直接入流点
                upstream_inflow.append(x_y_couple)
                # 搜索外边界上坡面间接入流点
                outline_upstream_search(xoff, yoff, water_buf, upstream_inflow)

    upstream_inflows.append(upstream_inflow)
Example #6
0
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)
Example #7
0
def water_order(old_water_bufs, new_water_bufs):
    global dataset_ol, dataset_acc
    recode_acc = []
    new_water_bufs.clear()
    # 各水体外边界上最大汇流累积量位置的集合
    surface_route_start = []
    for water_buf in old_water_bufs:
        # 获取此水体外边界最大汇流累积量
        max_acc = 0.0
        # 记录最大汇流累积量位置索引
        max_acc_point = water_buf[0]
        for point in water_buf:
            # 获得汇流累积量
            acc_point = cu.off_transform(point[0], point[1], dataset_ol,
                                         dataset_acc)
            acc_value = cu.get_raster_float_value(dataset_acc, acc_point[0],
                                                  acc_point[1])
            # 更新最大值记录
            if acc_value > max_acc:
                max_acc = acc_value
                max_acc_point = point
        # 插入排序
        if len(recode_acc) == 0:
            # 若为空则为第一个
            recode_acc.append(max_acc)
            new_water_bufs.append(water_buf)
            surface_route_start.append(max_acc_point)
        else:
            for index in range(len(recode_acc)):
                if recode_acc[index] > max_acc:
                    # 若为中间值则插入队
                    recode_acc.insert(index, max_acc)
                    new_water_bufs.insert(index, water_buf)
                    surface_route_start.insert(index, max_acc_point)
                    break
                if index == len(
                        recode_acc) - 1 and recode_acc[index] < max_acc:
                    # 若无更大值则追加到队尾
                    recode_acc.append(max_acc)
                    new_water_bufs.append(water_buf)
                    surface_route_start.append(max_acc_point)

    return surface_route_start
def spill_point_dir(inner_ras_indexes, dem_ds):
    global temp_ds
    # 内边界的高程
    inner_dem = []
    for ras_index in inner_ras_indexes:
        dem_value = cu.get_raster_float_value(dem_ds, ras_index[0],
                                              ras_index[1])
        inner_dem.append(dem_value)
    # 获得最低位置的索引
    spill_pt_index = list(map(inner_dem.index, heapq.nsmallest(1,
                                                               inner_dem)))[0]
    spill_pt = inner_ras_indexes[spill_pt_index]
    # 获得溢出方向
    spill_dir = get_spill_dir(inner_ras_indexes, spill_pt_index)
    # 得到接收点索引
    reception_pt = cu.get_to_point(spill_pt[0], spill_pt[1], spill_dir)

    cu.set_raster_int_value(temp_ds, spill_pt[0], spill_pt[1], spill_dir)

    return spill_pt, spill_dir, reception_pt
Example #9
0
def divide_outlet_to_group(outlets_order, acc_ds):
    acc_array = []
    # 获得所有出口点的acc值
    for outlet in outlets_order:
        acc_value = cu.get_raster_float_value(acc_ds, outlet[0], outlet[1])
        acc_array.append(acc_value)

    # 得到最大4个acc值所对应的数组索引
    max_4_acc = []
    max_4_index = []
    for index in range(len(acc_array)):
        acc_value = acc_array[index]
        max_4_acc.append(acc_value)
        max_4_index.append(index)
        if len(max_4_acc) > 4:
            array_index = list(
                map(max_4_acc.index, heapq.nlargest(4, max_4_acc)))
            n_max_4_acc = []
            n_max_4_index = []
            for n_index in array_index:
                n_max_4_acc.append(max_4_acc[n_index])
                n_max_4_index.append(max_4_index[n_index])
            max_4_acc = n_max_4_acc[:]
            max_4_index = n_max_4_index[:]

    # max_4_index = list(map(acc_array.index, heapq.nlargest(4, acc_array)))

    # 对4大acc对应索引从小到大排序
    max_4_index.sort()

    # 根据四大流域对夹杂的中间子流域分组
    odd_1 = outlets_order[0:max_4_index[0]]
    even_2 = [outlets_order[max_4_index[0]]]
    odd_3 = outlets_order[max_4_index[0] + 1:max_4_index[1]]
    even_4 = [outlets_order[max_4_index[1]]]
    odd_5 = outlets_order[max_4_index[1] + 1:max_4_index[2]]
    even_6 = [outlets_order[max_4_index[2]]]
    odd_7 = outlets_order[max_4_index[2] + 1:max_4_index[3]]
    even_8 = [outlets_order[max_4_index[3]]]
    odd_9 = outlets_order[max_4_index[3] + 1:]
    return [odd_1, even_2, odd_3, even_4, odd_5, even_6, odd_7, even_8, odd_9]
Example #10
0
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