基于A*算法的雷雨绕飞路径MATLAB实现

本文提出了一种基于A算法的雷雨绕飞路径规划方法。该方法首先生成模拟雷雨天气图并进行二值化处理,识别危险区域;然后检测计划航路中需要绕飞的航段,通过A算法为每个航段生成左右绕飞候选路径;接着进行视距优化和平行路径拓展以提高安全性;最后整合各航段最优路径构建完整绕飞航路。实验结果表明,该方法能有效避开危险区域,生成安全且长度优化的绕飞路径。关键创新点包括:1) 结合雷达天气数据的精细化处理;2) 多候选路径生成与优化机制;3) 完整航路构建策略。可视化界面直观展示了各阶段路径规划效果。

Matlab 复制代码
function thunderstorm_reroute_complete()
    % 设置参数
    map_size = [200, 150];
    num_storms = 12;
    max_storm_size = 20;
    intensity_threshold = 100;
    
    fprintf('开始雷雨绕飞路径规划...\n');
    
    % 1. 生成随机雷雨天气图
    fprintf('生成模拟雷雨天气图...\n');
    [radar_image, binary_map] = generate_random_weather_map(map_size, num_storms, max_storm_size);
    
    % 2. 定义计划航路
    fprintf('定义计划航路...\n');
    planned_route = [
        10, 20;
        150, 100;
        180, 130
    ];
    
    % 3. 处理天气雷达图
    fprintf('处理天气雷达图...\n');
    processed_binary_map = process_weather_radar(radar_image, intensity_threshold);
    
    % 4. 确定绕飞航段
    fprintf('确定绕飞航段...\n');
    [segments_to_reroute, middle_points, reroute_indices] = find_reroute_segments(planned_route, processed_binary_map);
    fprintf('找到 %d 个需要绕飞的航段\n', length(segments_to_reroute));
    
    % 5. A*路径规划
    fprintf('进行A*路径规划...\n');
    all_paths = a_star_path_planning_for_segments(segments_to_reroute, middle_points, processed_binary_map);
    
    % 6. 视距优化
    fprintf('进行视距优化...\n');
    optimized_paths = optimize_with_line_of_sight(all_paths, processed_binary_map);
    
    % 7. 平行拓展
    fprintf('进行平行拓展...\n');
    parallel_paths = parallel_expansion(optimized_paths, processed_binary_map, 5);
    
    % 8. 为每个航段选择最佳绕飞路径,并构建完整航路
    fprintf('构建完整最短绕飞航路...\n');
    [final_path, final_path_length, all_valid_paths] = find_and_construct_best_path(planned_route, reroute_indices, optimized_paths, parallel_paths, processed_binary_map);

    % 9. 可视化结果
    fprintf('生成可视化结果...\n');
    path_info.final_path = final_path;
    path_info.final_path_length = final_path_length;
    path_info.all_valid_paths = all_valid_paths;
    path_info.is_rerouted = ~isempty(reroute_indices); % 标记是否进行了绕飞
    visualize_results(radar_image, binary_map, planned_route, optimized_paths, parallel_paths, path_info);
    
    fprintf('雷雨绕飞路径规划完成!\n');
end

% --- 新增的核心逻辑:构建完整路径 ---
function [final_path, final_path_length, all_valid_paths] = find_and_construct_best_path(planned_route, reroute_indices, optimized_paths, parallel_paths, binary_map)
    % 如果没有需要绕飞的航段,直接返回原始路径
    if isempty(reroute_indices)
        final_path = planned_route;
        final_path_length = calculate_path_length(planned_route);
        all_valid_paths = {};
        return;
    end

    % 1. 为每个需要绕飞的航段选出最佳路径
    best_reroutes_per_segment = {};
    all_valid_paths = {};
    
    for i = 1:length(optimized_paths) % 对应每个需要绕飞的航段
        segment_candidates = {};
        
        % 收集该航段的所有候选路径 (主路径 + 平行路径)
        for j = 1:length(optimized_paths{i}) % 左/右绕飞
            path = optimized_paths{i}{j};
            if ~isempty(path) && check_entire_path_safety(path, binary_map)
                segment_candidates{end+1} = path;
                all_valid_paths{end+1} = path;
            end
        end
        for j = 1:length(parallel_paths{i}) % 平行拓展的路径
             for k = 1:length(parallel_paths{i}{j})
                path = parallel_paths{i}{j}{k};
                 if ~isempty(path) && check_entire_path_safety(path, binary_map)
                    segment_candidates{end+1} = path;
                    all_valid_paths{end+1} = path;
                 end
             end
        end

        % 从当前航段的候选中找到最短的
        best_segment_path = [];
        min_len = inf;
        for k = 1:length(segment_candidates)
            len = calculate_path_length(segment_candidates{k});
            if len < min_len
                min_len = len;
                best_segment_path = segment_candidates{k};
            end
        end
        best_reroutes_per_segment{i} = best_segment_path;
    end
    
    % 2. 构建完整路径
    final_path = [];
    last_planned_idx = 0;
    
    for i = 1:length(reroute_indices)
        reroute_idx = reroute_indices(i); % 这是计划航路中的航段索引
        
        % 添加上一个安全航段到当前绕飞航段起点之间的部分
        safe_segments = planned_route(last_planned_idx+1:reroute_idx, :);
        if ~isempty(final_path) && ~isempty(safe_segments)
            final_path = [final_path(1:end-1,:); safe_segments]; % 拼接,去除重复点
        elseif isempty(final_path)
            final_path = safe_segments;
        end
        
        % 添加当前航段的最佳绕飞路径
        rerouted_segment = best_reroutes_per_segment{i};
        if ~isempty(rerouted_segment)
            if ~isempty(final_path)
                final_path = [final_path(1:end-1,:); rerouted_segment];
            else
                final_path = rerouted_segment;
            end
        else
            % 如果绕飞失败,则添加原始航段(作为备用方案)
            original_segment = planned_route(reroute_idx:reroute_idx+1, :);
            if ~isempty(final_path)
                 final_path = [final_path(1:end-1,:); original_segment];
            else
                 final_path = original_segment;
            end
        end
        
        last_planned_idx = reroute_idx + 1;
    end
    
    % 添加最后一个绕飞航段到终点的剩余安全部分
    if last_planned_idx <= size(planned_route, 1)
        remaining_segments = planned_route(last_planned_idx:end, :);
         if ~isempty(final_path) && ~isempty(remaining_segments)
            final_path = [final_path(1:end-1,:); remaining_segments];
         elseif isempty(final_path) % 如果全程都无需绕飞,但逻辑走到这里说明有误,作为保险
            final_path = planned_route;
         end
    end
    
    final_path_length = calculate_path_length(final_path);
end


% --- 其他函数(保持不变或微小修正) ---

function [radar_image, binary_map] = generate_random_weather_map(map_size, num_storms, max_storm_size)
    width = map_size(1);
    height = map_size(2);
    radar_image = ones(height, width, 3);
    weather_intensity = zeros(height, width);
    for i = 1:num_storms
        center_x = randi([max_storm_size+1, width - max_storm_size - 1]);
        center_y = randi([max_storm_size+1, height - max_storm_size - 1]);
        min_size = max(5, floor(max_storm_size/3));
        storm_width = randi([min_size, max_storm_size]);
        storm_height = randi([min_size, max_storm_size]);
        max_intensity = randi([150, 255]);
        for x = max(1, center_x-storm_width):min(width, center_x+storm_width)
            for y = max(1, center_y-storm_height):min(height, center_y+storm_height)
                dx = (x - center_x) / storm_width;
                dy = (y - center_y) / storm_height;
                distance = sqrt(dx^2 + dy^2);
                if distance <= 1
                    intensity = max_intensity * (1 - distance);
                    weather_intensity(y,x) = max(weather_intensity(y,x), intensity);
                end
            end
        end
    end
    noise_density = 0.005;
    num_noise_points = round(noise_density * width * height);
    for i = 1:num_noise_points
        x = randi(width);
        y = randi(height);
        weather_intensity(y,x) = max(weather_intensity(y,x), randi([100, 200]));
    end
    for i = 1:height
        for j = 1:width
            intensity = weather_intensity(i,j);
            if intensity == 0, radar_image(i,j,:) = [0.2, 0.5, 1.0];
            elseif intensity < 50, radar_image(i,j,:) = [0.6, 0.9, 0.6];
            elseif intensity < 100, radar_image(i,j,:) = [1.0, 1.0, 0.4];
            elseif intensity < 150, radar_image(i,j,:) = [1.0, 0.6, 0.2];
            else, radar_image(i,j,:) = [1.0, 0.2, 0.2];
            end
        end
    end
    binary_map = weather_intensity < 50;
    figure('Position', [100, 100, 1200, 500]);
    subplot(1,2,1); imshow(radar_image); title('模拟雷达天气图');
    subplot(1,2,2); imagesc(binary_map); colormap([1,1,1; 0,0,0]); 
    title('二值化天气地图 (白色=安全, 黑色=危险)'); colorbar; axis equal;
end

function processed_binary_map = process_weather_radar(radar_image, intensity_threshold)
    weather_intensity = double(radar_image(:,:,1)) * 255;
    binary_map = weather_intensity < intensity_threshold;
    se = strel('disk', 2);
    binary_map = imclose(binary_map, se);
    se_dilate = strel('disk', 3);
    danger_zones = imdilate(~binary_map, se_dilate);
    processed_binary_map = binary_map & ~danger_zones;
    processed_binary_map = bwareaopen(processed_binary_map, 10);
end

function [segments, middle_points, reroute_indices] = find_reroute_segments(planned_route, binary_map)
    segments = {};
    middle_points = [];
    reroute_indices = []; % 新增:记录需要绕飞的航段索引
    for i = 1:size(planned_route,1)-1
        start_point = planned_route(i,:);
        end_point = planned_route(i+1,:);
        if check_weather_crossing_enhanced(start_point, end_point, binary_map)
            segments{end+1} = [start_point; end_point];
            reroute_indices(end+1) = i; % 记录索引
            [left_mid, right_mid] = find_safe_middle_points(start_point, end_point, binary_map);
            middle_points = [middle_points; left_mid; right_mid];
        end
    end
end

function crossing = check_weather_crossing_enhanced(start_point, end_point, binary_map)
    num_points = max(ceil(norm(end_point - start_point)) * 3, 20);
    x_points = linspace(start_point(1), end_point(1), num_points);
    y_points = linspace(start_point(2), end_point(2), num_points);
    for i = 1:num_points
        if ~is_safe_point([x_points(i), y_points(i)], binary_map)
            crossing = true; return;
        end
    end
    perpendicular = [- (end_point(2)-start_point(2)), (end_point(1)-start_point(1))];
    if norm(perpendicular) > 0
        perpendicular = perpendicular / norm(perpendicular);
        for i = 1:num_points
            left_point = [x_points(i), y_points(i)] + 5 * perpendicular;
            if ~is_safe_point(left_point, binary_map)
                crossing = true; return;
            end
            right_point = [x_points(i), y_points(i)] - 5 * perpendicular;
            if ~is_safe_point(right_point, binary_map)
                crossing = true; return;
            end
        end
    end
    crossing = false;
end

function [left_mid, right_mid] = find_safe_middle_points(start_point, end_point, binary_map)
    segment_vector = end_point - start_point;
    segment_length = norm(segment_vector);
    if segment_length > 0
        segment_dir = segment_vector / segment_length;
        perpendicular = [-segment_dir(2), segment_dir(1)];
    else, perpendicular = [1, 0]; end
    test_positions = [0.3, 0.5, 0.7];
    left_mid = []; right_mid = [];
    for pos = test_positions
        base_point = start_point + pos * segment_vector;
        if isempty(left_mid)
            for offset = [10, 15, 20, 25, 30]
                candidate = base_point + offset * perpendicular;
                if is_safe_point(candidate, binary_map) && check_path_safety(start_point, candidate, binary_map) && check_path_safety(candidate, end_point, binary_map)
                    left_mid = candidate; break;
                end
            end
        end
        if isempty(right_mid)
            for offset = [10, 15, 20, 25, 30]
                candidate = base_point - offset * perpendicular;
                if is_safe_point(candidate, binary_map) && check_path_safety(start_point, candidate, binary_map) && check_path_safety(candidate, end_point, binary_map)
                    right_mid = candidate; break;
                end
            end
        end
        if ~isempty(left_mid) && ~isempty(right_mid), break; end
    end
    if isempty(left_mid), left_mid = start_point + 0.25 * segment_vector + 15 * perpendicular; end
    if isempty(right_mid), right_mid = start_point + 0.75 * segment_vector - 15 * perpendicular; end
end

function safe = check_path_safety(point1, point2, binary_map)
    num_points = max(ceil(norm(point2 - point1)) * 2, 10);
    x_points = linspace(point1(1), point2(1), num_points);
    y_points = linspace(point1(2), point2(2), num_points);
    for i = 1:num_points
        if ~is_safe_point([x_points(i), y_points(i)], binary_map)
            safe = false; return;
        end
    end
    safe = true;
end

function all_paths = a_star_path_planning_for_segments(segments, middle_points, binary_map)
    all_paths = {};
    for i = 1:length(segments)
        segment = segments{i}; start_point = segment(1,:); end_point = segment(2,:);
        fprintf('规划航段 %d: 从[%.1f,%.1f]到[%.1f,%.1f]\n', i, start_point(1), start_point(2), end_point(1), end_point(2));
        left_mid = middle_points((i-1)*2+1,:);
        path_left1 = a_star_path_planning(start_point, left_mid, binary_map);
        path_left2 = a_star_path_planning(left_mid, end_point, binary_map);
        if ~isempty(path_left1) && ~isempty(path_left2), path_left = [path_left1; path_left2(2:end,:)];
        else, path_left = a_star_path_planning(start_point, end_point, binary_map);
            if isempty(path_left), path_left = [start_point; end_point]; fprintf('  左侧路径规划失败,使用直线路径\n'); end
        end
        right_mid = middle_points((i-1)*2+2,:);
        path_right1 = a_star_path_planning(start_point, right_mid, binary_map);
        path_right2 = a_star_path_planning(right_mid, end_point, binary_map);
        if ~isempty(path_right1) && ~isempty(path_right2), path_right = [path_right1; path_right2(2:end,:)];
        else, path_right = a_star_path_planning(start_point, end_point, binary_map);
            if isempty(path_right), path_right = [start_point; end_point]; fprintf('  右侧路径规划失败,使用直线路径\n'); end
        end
        all_paths{end+1} = {path_left, path_right};
    end
end

function path = a_star_path_planning(start_point, end_point, binary_map)
    start = round(start_point); goal = round(end_point);
    if ~is_safe_point(start, binary_map), start = find_nearest_safe_point(start, binary_map, 20); if isempty(start), path = []; return; end; end
    if ~is_safe_point(goal, binary_map), goal = find_nearest_safe_point(goal, binary_map, 20); if isempty(goal), path = []; return; end; end
    [height, width] = size(binary_map);
    g_score = inf(height, width); f_score = inf(height, width); closed_map = false(height, width);
    parent_x = zeros(height, width); parent_y = zeros(height, width);
    g_score(start(2), start(1)) = 0; f_score(start(2), start(1)) = heuristic(start, goal);
    directions = [0,1,1.0; 1,0,1.0; 0,-1,1.0; -1,0,1.0; 1,1,1.414; 1,-1,1.414; -1,1,1.414; -1,-1,1.414];
    open_list = [struct('x', start(1), 'y', start(2), 'f', f_score(start(2), start(1)))];
    max_iter = height * width * 2; iter = 0;
    while ~isempty(open_list) && iter < max_iter
        iter = iter + 1;
        [~, min_idx] = min([open_list.f]); current = open_list(min_idx); open_list(min_idx) = [];
        x_curr = current.x; y_curr = current.y;
        if x_curr == goal(1) && y_curr == goal(2), path = reconstruct_path_improved(parent_x, parent_y, start, goal); return; end
        if closed_map(y_curr, x_curr), continue; end
        closed_map(y_curr, x_curr) = true;
        for d = 1:size(directions, 1)
            dx = directions(d, 1); dy = directions(d, 2); move_cost = directions(d, 3);
            x_neighbor = x_curr + dx; y_neighbor = y_curr + dy;
            if x_neighbor < 1 || x_neighbor > width || y_neighbor < 1 || y_neighbor > height, continue; end
            if ~binary_map(y_neighbor, x_neighbor), continue; end
            tentative_g = g_score(y_curr, x_curr) + move_cost;
            if tentative_g < g_score(y_neighbor, x_neighbor)
                parent_x(y_neighbor, x_neighbor) = x_curr; parent_y(y_neighbor, x_neighbor) = y_curr;
                g_score(y_neighbor, x_neighbor) = tentative_g;
                f_score(y_neighbor, x_neighbor) = tentative_g + heuristic([x_neighbor, y_neighbor], goal);
                if ~closed_map(y_neighbor, x_neighbor), open_list = [open_list; struct('x', x_neighbor, 'y', y_neighbor, 'f', f_score(y_neighbor, x_neighbor))]; end
            end
        end
    end
    path = [];
end

function point = find_nearest_safe_point(point, binary_map, max_radius)
    for radius = 1:max_radius
        for dx = -radius:radius, for dy = -radius:radius
            test_point = round(point + [dx, dy]);
            if is_safe_point(test_point, binary_map), point = test_point; return; end
        end, end
    end
    point = [];
end

function h = heuristic(point1, point2), h = norm(point1 - point2); end

function path = reconstruct_path_improved(parent_x, parent_y, start, goal)
    path = []; x_curr = goal(1); y_curr = goal(2);
    while x_curr ~= start(1) || y_curr ~= start(2)
        path = [x_curr, y_curr; path];
        x_prev = parent_x(y_curr, x_curr); y_prev = parent_y(y_curr, x_curr);
        if x_prev == 0 && y_prev == 0, break; end
        x_curr = x_prev; y_curr = y_prev;
    end
    path = [start; path];
end

function optimized_paths = optimize_with_line_of_sight(paths, binary_map)
    optimized_paths = {};
    for i = 1:length(paths)
        optimized_paths{i} = {};
        for j = 1:length(paths{i})
            path = paths{i}{j};
            if isempty(path), optimized_paths{i}{j} = path;
            else, optimized_paths{i}{j} = line_of_sight_optimization(path, binary_map); end
        end
    end
end

function optimized_path = line_of_sight_optimization(path, binary_map)
    if isempty(path) || size(path, 1) < 3, optimized_path = path; return; end
    optimized_path = path(1,:); current_idx = 1;
    while current_idx < size(path, 1)
        found = false;
        for i = size(path, 1):-1:current_idx+1
            if check_line_safety_enhanced(path(current_idx,:), path(i,:), binary_map)
                if validate_optimized_segment(optimized_path(end,:), path(i,:), binary_map)
                    optimized_path = [optimized_path; path(i,:)]; current_idx = i; found = true; break;
                end
            end
        end
        if ~found, current_idx = current_idx + 1; optimized_path = [optimized_path; path(current_idx,:)]; end
    end
end

function safe = check_line_safety_enhanced(point1, point2, binary_map)
    num_points = max(ceil(norm(point2 - point1)) * 3, 15);
    x_points = linspace(point1(1), point2(1), num_points);
    y_points = linspace(point1(2), point2(2), num_points);
    for i = 1:num_points
        if ~is_safe_point([x_points(i), y_points(i)], binary_map), safe = false; return; end
        if i > 1 && i < num_points
            dx = x_points(i) - x_points(i-1); dy = y_points(i) - y_points(i-1);
            if abs(dx) + abs(dy) > 0
                perpendicular = [-dy, dx] / norm([-dy, dx]);
                for offset = [2, 4]
                    left_point = [x_points(i), y_points(i)] + offset * perpendicular;
                    right_point = [x_points(i), y_points(i)] - offset * perpendicular;
                    if ~is_safe_point(left_point, binary_map) || ~is_safe_point(right_point, binary_map), safe = false; return; end
                end
            end
        end
    end
    safe = true;
end

function valid = validate_optimized_segment(start_point, end_point, binary_map)
    num_points = max(ceil(norm(end_point - start_point)) * 2, 10);
    x_points = linspace(start_point(1), end_point(1), num_points);
    y_points = linspace(start_point(2), end_point(2), num_points);
    for i = 1:num_points
        if ~is_safe_point([x_points(i), y_points(i)], binary_map), valid = false; return; end
    end
    valid = true;
end

function parallel_paths = parallel_expansion(paths, binary_map, offset_distance)
    parallel_paths = {};
    for i = 1:length(paths)
        parallel_paths{i} = {};
        for j = 1:length(paths{i})
            original_path = paths{i}{j};
            if isempty(original_path), parallel_paths{i}{j} ={};
            else, parallel_paths{i}{j} = parallel_expansion_for_path(original_path, binary_map, offset_distance); end
        end
    end
end

function parallel_path_list = parallel_expansion_for_path(original_path, binary_map, offset_distance)
    parallel_path_list = {};
    if size(original_path, 1) < 2, return; end
    for direction = [-1, 1]
        offset = offset_distance * direction; new_path = []; valid_path = true;
        for i = 1:size(original_path, 1)
            if i == 1, segment_vector = original_path(2,:) - original_path(1,:);
            elseif i == size(original_path, 1), segment_vector = original_path(end,:) - original_path(end-1,:);
            else, prev_vector = original_path(i,:) - original_path(i-1,:); next_vector = original_path(i+1,:) - original_path(i,:); segment_vector = (prev_vector + next_vector) / 2;
            end
            if norm(segment_vector) > 0.1, normal_vector = [-segment_vector(2), segment_vector(1)] / norm([-segment_vector(2), segment_vector(1)]);
            else, normal_vector = [1, 0]; end
            new_point = original_path(i,:) + offset * normal_vector; new_point_round = round(new_point);
            if is_safe_point(new_point_round, binary_map), new_path = [new_path; new_point_round];
            else, safe_point = find_nearest_safe_point(new_point_round, binary_map, 5);
                if ~isempty(safe_point), new_path = [new_path; safe_point];
                else, valid_path = false; break; end
            end
        end
        if valid_path && size(new_path, 1) == size(original_path, 1), parallel_path_list{end+1} = new_path; end
    end
end

function safe = check_entire_path_safety(path, binary_map)
    for i = 1:size(path, 1)-1
        if ~check_line_safety_enhanced(path(i,:), path(i+1,:), binary_map)
            safe = false; return;
        end
    end
    safe = true;
end

function length = calculate_path_length(path)
    length = 0;
    for i = 1:size(path,1)-1
        length = length + norm(path(i+1,:) - path(i,:));
    end
end

function safe = is_safe_point(point, binary_map)
    x = round(point(1)); y = round(point(2)); [height, width] = size(binary_map);
    safe = x >= 1 && x <= width && y >= 1 && y <= height && binary_map(y, x) == 1;
end


% --- 关键的可视化函数(已大幅优化) ---
function visualize_results(radar_image, binary_map, planned_route, optimized_paths, parallel_paths, path_info)
    figure('Position', [100, 100, 1500, 1000]);
    
    % 子图1-4: 保持不变,用于展示中间过程
    subplot(2,3,1); imshow(radar_image); hold on;
    plot(planned_route(:,1), planned_route(:,2), 'g-', 'LineWidth', 3, 'DisplayName', '计划航路');
    plot(planned_route(:,1), planned_route(:,2), 'go', 'MarkerSize', 8, 'MarkerFaceColor', 'g');
    title('模拟雷达天气图和计划航路'); legend('Location', 'best');
    
    subplot(2,3,2); imagesc(binary_map); colormap(gca, [0.3,0.3,0.3; 1,1,1]); hold on;
    plot(planned_route(:,1), planned_route(:,2), 'g-', 'LineWidth', 3);
    colors = ['r', 'b', 'm', 'c', 'y']; path_count = 0;
    for i = 1:length(optimized_paths)
        for j = 1:length(optimized_paths{i})
            path = optimized_paths{i}{j};
            if ~isempty(path) && size(path, 2) == 2, color_idx = mod(path_count, length(colors)) + 1;
                plot(path(:,1), path(:,2), [colors(color_idx) '-'], 'LineWidth', 2); path_count = path_count + 1;
            end
        end
    end
    title('A* 初始绕飞路径'); axis equal;

    subplot(2,3,3); imagesc(binary_map); colormap(gca, [0.3,0.3,0.3; 1,1,1]); hold on;
    plot(planned_route(:,1), planned_route(:,2), 'g-', 'LineWidth', 3); path_count = 0;
    for i = 1:length(optimized_paths)
        for j = 1:length(optimized_paths{i})
            path = optimized_paths{i}{j};
            if ~isempty(path) && size(path, 2) == 2, color_idx = mod(path_count, length(colors)) + 1;
                optimized_path = line_of_sight_optimization(path, binary_map);
                plot(optimized_path(:,1), optimized_path(:,2), [colors(color_idx) '-'], 'LineWidth', 2);
                plot(optimized_path(:,1), optimized_path(:,2), [colors(color_idx) 'o'], 'MarkerSize', 4); path_count = path_count + 1;
            end
        end
    end
    title('视距优化后路径'); axis equal;
    
    subplot(2,3,4); imagesc(binary_map); colormap(gca, [0.3,0.3,0.3; 1,1,1]); hold on;
    plot(planned_route(:,1), planned_route(:,2), 'g-', 'LineWidth', 3);
    colors = {'r', 'b', 'm', 'c', 'y', 'k'}; path_count = 0;
    for i = 1:length(parallel_paths)
        for j = 1:length(parallel_paths{i})
            path_group = parallel_paths{i}{j};
            for k = 1:length(path_group)
                path = path_group{k};
                if ~isempty(path) && size(path, 2) == 2 && size(path, 1) >= 2, path_count = path_count + 1;
                    color_idx = mod(path_count - 1, length(colors)) + 1;
                    plot(path(:,1), path(:,2), 'Color', colors{color_idx}, 'LineStyle', '--', 'LineWidth', 2);
                end
            end
        end
    end
    title('平行拓展路径'); axis equal;

    % 子图5: 最终结果 - 完整最短绕飞航路
    subplot(2,3,[5,6]); % 合并两个子图以获得更大的显示空间
    imagesc(binary_map);
    colormap(gca, [0.3,0.3,0.3; 1,1,1]);
    hold on;
    
    % 绘制危险区域边界
    boundaries = bwboundaries(~binary_map);
    for k = 1:length(boundaries)
        boundary = boundaries{k};
        plot(boundary(:,2), boundary(:,1), 'Color', [1, 0.4, 0.4, 0.7], 'LineWidth', 1);
    end
    
    % 绘制原始计划航路(半透明虚线,作为对比)
    plot(planned_route(:,1), planned_route(:,2), 'g--', 'LineWidth', 2, 'DisplayName', '原始计划航路');
    
    % 绘制最终的完整航路
    final_path = path_info.final_path;
    if isfield(path_info, 'final_path') && ~isempty(final_path) && ismatrix(final_path) && size(final_path, 2) == 2 && size(final_path, 1) >= 2
        % 使用醒目的颜色绘制最终路径
        plot(final_path(:,1), final_path(:,2), 'm-', 'LineWidth', 3, 'DisplayName', '最终完整航路');
        plot(final_path(1,1), final_path(1,2), 'o', 'MarkerSize', 10, 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'g', 'LineWidth', 1.5); % 起点
        plot(final_path(end,1), final_path(end,2), 's', 'MarkerSize', 10, 'MarkerEdgeColor', 'k', 'MarkerFaceColor', 'r', 'LineWidth', 1.5); % 终点

        % 添加路径信息文本
        info_text = {};
        if path_info.is_rerouted
            title_str = '最终完整绕飞航路';
            info_text{1} = sprintf('完整航路长度: %.2f', path_info.final_path_length);
            info_text{2} = sprintf('原始航路长度: %.2f', calculate_path_length(planned_route));
            info_text{3} = sprintf('共找到 %d 条有效绕飞路径', length(path_info.all_valid_paths));
        else
            title_str = '全程安全,无需绕飞';
            info_text{1} = sprintf('航路长度: %.2f (原始计划航路)', path_info.final_path_length);
        end
        title(title_str, 'FontSize', 14);
        text(10, 20, info_text, 'FontSize', 12, 'FontWeight', 'bold', 'BackgroundColor', [1,1,1,0.7], 'VerticalAlignment', 'top');

    else
        title('未能生成有效的最终航路', 'Color', 'r');
    end
    
    legend('Location', 'best');
    axis equal;
    hold off;
end

相关推荐
_F_y42 分钟前
二分:山脉数组的峰顶索引、寻找峰值、寻找旋转排序数组中的最小值、点名
c++·算法
Elias不吃糖1 小时前
克隆图(LeetCode 133)——用数组做映射的 DFS 解法
c++·算法·leetcode·深度优先
iiiiii111 小时前
【论文阅读笔记】IDAQ:离线元强化学习中的分布内在线适应
论文阅读·人工智能·笔记·学习·算法·机器学习·强化学习
秋深枫叶红1 小时前
嵌入式第二十三篇——数据结构基本概念
linux·数据结构·学习·算法
Zsy_0510031 小时前
【数据结构】二叉树介绍及C语言代码实现
c语言·数据结构·算法
Ayanami_Reii1 小时前
基础数学算法-移棋子游戏
数学·算法·游戏·博弈论·sg函数
谁刺我心1 小时前
蓝桥杯C++常用STL
c++·算法·蓝桥杯
wubba lubba dub dub7501 小时前
第二十七周 学习周报
学习·算法·机器学习
小白程序员成长日记1 小时前
力扣每日一题 2025.11.30
数据结构·算法·leetcode