def site_interpolation(edges, selected_points):
    global travel_range
    edges_fine = []
    selected_points_fine = copy.copy(selected_points)
    for edge in edges:
        start = selected_points[edge[0]]
        end = selected_points[edge[1]]
        st.reset()
        length, path = pa.find(start, end, 0, [])
        if min(length, st.global_min) <= travel_range:
            edges_fine.append(edge)
        while min(length, st.global_min) > travel_range:
            print(start, '\n', end)
            reach = get_P(point_coverage(start, mode='travel'))
            print('covered')
            line = ge.LineString([start, end])
            new_site = reach.exterior.intersection(line)
            selected_points_fine.append(new_site)
            edges_fine.append([edge[0], len(selected_points_fine) - 1])
            edges_fine.append([len(selected_points_fine) - 1, edge[1]])
            start = new_site
            st.reset()
            length, path = pa.find(start, end, 0, [])
            print('interpolation')
    print('interpolation done')
    return edges_fine, selected_points_fine
def point_coverage(point, mode='cover'):
    global cover_range
    global travel_range
    global obs
    # global rdif
    points = [None for _ in range(65)]
    if mode == 'cover':
        nowr = cover_range
    else:
        nowr = travel_range
    rdif = (nowr * 3) / 100
    while not all(points):
        # print(nowr)
        if nowr <= 0:
            break
        circle = get_circle(point, nowr)
        # print(circle)
        for i, circle_point in enumerate(circle):
            if not points[i]:
                # print('input',point,circle_point)
                # print(nowr)
                st.reset()
                # print(point,'\n',circle_point)
                dis, path = pa.find(point, circle_point, 0, [])
                # print(dis,st.global_min)
                # if i==65:
                # stack.append([point,circle_point])
                if min(dis, st.global_min) <= cover_range:
                    points[i] = circle_point
        nowr -= rdif
    return points
def ob_dis():
    stack = [0 for _ in range(len(st.obs))]
    for i, ob in enumerate(st.obs):
        # print(i)
        st.reset()
        lenght, path = pa.find(st.pstart, ob.centroid, 0, [])
        stack[i] = min(lenght, st.global_min)
    with open("D:/UAV project/obs_distance.csv", "w+") as my_csv:
        csvWriter = csv.writer(my_csv, delimiter=',')
        csvWriter.writerow(stack)
    print('obs_distance to start generated')
    return
def picked_sites_dis(selected_points_this):
    # global ref
    # ref=selected_points_this
    dis_mat = [[-1 for _ in range(len(selected_points_this))]
               for _ in range(len(selected_points_this))]
    i = 0
    while i < len(selected_points_this) - 1:
        # print('i',i,len(selected_points_this))
        for j in range(i + 1, len(selected_points_this)):
            st.reset()
            # print(i,j)
            # print(type(i),type(j))
            # print(selected_points_this[i],'\n',selected_points_this[j])
            # print(type(selected_points_this[i]),type(selected_points_this[j]))
            lenght, path = pa.find(selected_points_this[i],
                                   selected_points_this[j], 0, [])
            # print('min',st.global_min,'lenght',lenght,'\n')
            dis_mat[i][j] = min(st.global_min, lenght)
        # print('pre',i,len(selected_points_this))
        i += 1
    # csv_write(dis_mat,"picked_sites_dis")
    print('sites dis calculated')
    return dis_mat
def branch_and_cut(
        dis_mat,
        task_number,
        solver='exact',
        plot=1):  #generate task permutation find pareto optimality solution
    task = task_generator(len(dis_mat), task_number)

    def cal_fitness(dis, en, a=0.1):
        return a * en + (1 - a) * dis

    def exact_solver(dis_mat, task):
        min_dis_all = float('inf')
        min_en_all = float('inf')
        max_fitness = float('inf')
        solution = [[], [], []]
        for this_task in itertools.permutations(task):
            this_task = [0] + list(this_task) + [0]
            dis_all = 0
            en_all = 0
            for i in range(0, len(this_task) - 1):
                mi, ma = min(this_task[i],
                             this_task[i + 1]), max(this_task[i],
                                                    this_task[i + 1])
                dis_all += dis_mat[mi][ma]
                en_all += cal_travel_cost(
                    dis_mat[mi][ma],
                    10 * ((len(this_task) - 2 - i) / (len(this_task) - 2)))
                fitness = cal_fitness(dis=dis_all, en=en_all)
                if dis_all < min_dis_all:
                    min_dis_all = dis_all
                    solution[0] = [this_task, dis_all * 100, en_all, fitness]
                if en_all < min_en_all:
                    min_en_all = en_all
                    solution[1] = [this_task, dis_all * 100, en_all, fitness]
                if fitness < max_fitness:
                    max_fitness = fitness
                    solution[2] = [this_task, dis_all * 100, en_all, fitness]
        return solution

    if solver == 'exact':
        solution = exact_solver(dis_mat, task)
        print(solution)
    with open("D:/UAV project/solution.txt", "w+") as f:
        f.write('total_dis(km),total_energy_consumption(battery),fitness\n')
        f.write('min time solution\n')
        f.write(str(solution[0]))
        f.write('min energy consumption_solution\n')
        f.write(str(solution[1]))
        f.write('max fitness solution\n')
        f.write(str(solution[2]))
    print('task planning done')
    if plot:
        edges = []
        task_route = solution[plot - 1][0]
        for i in range(len(task_route) - 1):
            st.reset()
            lenght, path = pa.find(selected_points_raw[task_route[i]],
                                   selected_points_raw[task_route[i + 1]], 0,
                                   [])
            if st.global_path:
                edges.extend(st.global_path)
            else:
                edges.extend(path)
        p([st.obs,
           pan.GeoSeries(selected_points_raw),
           pan.GeoSeries(edges)], ['red', 'black'])
        print('route plotted')
    return