随机生成400个点,再去除其中的120个点作为‘路障’。采用dijkstra算法寻找最短路径。
主函数: main.m
clc,clear all
% Define the size of the map
sideLength = 20;
nodes = sideLength*sideLength;
removed_num = 120;
% Generate the map
[routing_value,mapping] = mapGenerator(sideLength,removed_num)
% Calculate the shorest path
[dist,selectedNode] = Mydijkstra(routing_value,1,nodes)
% Draw the line
drawLine(selectedNode,mapping)
思路:
step1:定义地图大小/内容
step2:把随机生成的‘视觉地图’信息载入‘矩阵地图’
step3:使用dijkstra原理寻找最短路径
step4:连点成线
生成地图函数: mapGenerator.m
function [routing_value, mapping] = mapGenerator(edge,removed_num)
% edge: the side length of the map
nodes = edge * edge; % Total elements in the routing table
routing_value = ones(nodes,nodes)*999; % Set the initial distance to infinity(999)
mapping = zeros(2,nodes); % The mapping matrix of map position and routing value table
% updating the routing value from the (1,1) dot.
for y = 1:edge % x. Y represents two axes in the map
y_original = y;
for x = 1:edge
y = y_original;
x_original = x;
h = x_original+(y_original-1)*edge;
mapping(1,h)=x_original;
mapping(2,h)=y_original;
% right adjacency
if(x_original<edge)
x = x+1;
k = (y-1)*edge + x; % calculate the neighbor's number which is the column of routing_value table
routing_value(h,k) = 1;
routing_value(k,h) = 1; % because it is adjacent, the reverse is also true
% h,k
end
% upper adjacency
if(y_original<edge)
x = x_original;
y = y+1;
k = (y-1)*edge + x; % calculate the neighbor's number which is the column of routing_value table
routing_value(h,k) = 1;
routing_value(k,h) = 1; % because it is adjacent, the reverse is also true
% h,k
end
% right upper corner
% condition: not in the right border and not in the upper border.
if(x_original<edge) && (y_original<edge)
x = x+1;
k = (y-1)*edge + x; % calculate the neighbor's number which is the column of routing_value table
routing_value(h,k) = 1.4;
routing_value(k,h) = 1.4; % because it is adjacent, the reverse is also true
% h,k
end
% left upper corner
% condition: not in the left border and not in the upper border
if(x_original>1) && (y_original<edge)
x=x_original-1;
k = (y-1)*edge + x; % calculate the neighbor's number which is the column of routing_value table
routing_value(h,k) = 1.4;
routing_value(k,h) = 1.4; % because it is adjacent, the reverse is also true
% h,k
end
end
end
% !!! step2: draw dots on the map
for i = 1:edge
x = i;
for j = 1:edge
y = j;
scatter(x,y,'green');
hold on
end
end
% !!! step3: remove 3/10 dots on the map and re-calculate the routing table
record = zeros(1,size(routing_value,1)); % put the removed dots in record list to prevent removing more than once.
for i = 1:removed_num
x = randperm(edge,1); % the x axis of the dot, x<=edge
y = randperm(edge,1);
hk = x+(y-1)*edge;
% can not remove start point and destination point.
% and can not remove one point twice
if(hk ~= nodes && hk ~= 1 && record(hk) ~= 1)
scatter(x,y,'red');
record(hk) = 1;
% set the removing nodes' value routing to infinite(999)
routing_value(hk,:)=999;
routing_value(:,hk)=999;
else
removed_num = removed_num+1;
end
end
把 ‘视觉地图’ 信息载入矩阵的原理/逻辑:
如下表格所示,是 ‘视觉地图’ 中 ‘地点’ 的坐标信息,以中心地点的坐标为(x,y)为例,它与八个邻居坐标关系如下。
(x-1, y+1) | (x, y+1) | (x+1, y+1) |
(x-1, y) | (x, y) | (x+1, y) |
(x-1, y-1) | (x, y-1) | (x+1, y-1) |
所以当我们生成‘ 矩阵地图 (用矩阵记录地图中的路径信息) ’时,可以(对总共400个点)从左往右,由下至上地更新每一个点和它邻居的关系。由于两点间路径值一致 (i.e. A-->B的距离=B-->A的距离),所以避免重复,对于当前‘点’,我们只需要写入‘当前点’ 到 ‘当前点之后/ 没有出现过的邻居’ 的距离值。
以中心地点的坐标为(x,y)为例,它之后的邻居为:
(x-1, y+1) | (x, y+1) | (x+1, y+1) |
(x, y) | (x+1, y) | |
(x+1, y-1) |
PS: 我们还需要考虑到‘顶点’,如果当前点为顶点,或在边缘线之上,需要补充限制条件,以防程序报错。
Dijkstra’s 算法函数: Mydijkstra.m
function [dist,selectedNode] = Mydijkstra(routing_value,start,dest)
% setting
routers = size(routing_value,1); % statistic total number of points(the row number of r_v table)
Selected(1) = dest; % set of selected points
Unselected = 1:routers; % set of unselected points
Unselected(dest) = [];
Distance = zeros(2,routers); % inisialize all the path length
Distance(1,:) = 1:routers; % A 2*7 matrix to record the distance from every point to the destination
Distance(2,1:routers) = routing_value(dest,1:routers); % assign the value
new_Distance = Distance; % A 2*7 matrix used to compare with the original links distance
min_distance = Distance; % Initialize minimum distance
min_distance(:,dest) = []; % deleted the length from destination to destination
% initialize path
path = zeros(2,routers);
path(1,:) = 1:routers;
path(2,Distance(2,:)~=999) = dest; % '999' stand for cannot reach
% finding the shorest path
while ~isempty(Unselected) % until the unselected set is empty
index = find( min_distance(2,:)==min(min_distance(2,:)),1 ); % find the shorest path among the leftover points
k = min_distance(1,index);
% update the point
Selected = [Selected,k]; % add k to Selected set
Unselected(Unselected==k) = []; % deleted from the set of Unselected
%calculate the distance
new_Distance(2,:) = routing_value(k,1:routers)+Distance(2,k);
min_distance = min(Distance,new_Distance); % compare with the former value and select the min
% update the path
path( 2, min_distance(2,:)~=Distance(2,:) ) = k; % path used to record the former 'jump' of the router
Distance = min_distance;
min_distance(:,Selected) = [];
end
dist = Distance(2,start);
% output
selectedNode=[];
fprintf('the path is:');
while start ~= dest % end when reach the destination
selectedNode = [selectedNode,start];
fprintf('%d-->',start);
next = path(2,start);
start = next;
end
fprintf('%d\n',dest); % print out the destination
selectedNode = [selectedNode,dest];
selectedNode
fprintf('The length of the shorest path:%f\n',dist);
end
此部分参考:
乐观的lishan:最短路径 Dijkstra算法的Matlab代码实现_乐观的lishan的博客-CSDN博客_dijkstra matlab
连点成线函数:drawLine.m
function [] = drawLine(selectedNode,mapping)
% step5: draw the line
pathlength = size(selectedNode,2)
for i=1:pathlength-1
line([mapping(1,selectedNode(i)),mapping(1,selectedNode(i+1))], ...
[mapping(2,selectedNode(i)),mapping(2,selectedNode(i+1))], ...
'linewidth',3,'color','b')
end
设置线段的颜色,粗细。在‘视觉地图’中呈现出最短路径。