首先,读取并显示图片。
main.m
clear all;
clc;
img=imread('img.png');
并且手动选择顶点
[p1,p2]=getpts;
hold on;
之后开始循环遍历顶点
for n=1:length(p1)
for m=n+1:length(p1)
if (square(p1(n),p1(m),p2(n),p2(m),p1,p2) == 0) & (triangle(p1(n),p1(m),p2(n),p2(m),p1,p2)) == 0 & (star(p1(n),p1(m),p2(n),p2(m),p1,p2)) == 0
plot([p1(n),p1(m)],[p2(n),p2(m)],'b-'); %连接两个符合条件的顶点
end
end
end
在连接两个顶点之前,先要if判断这两点连线是否经过障碍物。主要原理是:将直线写成y=kx+b的形式,将图形的所有顶点坐标带入y-kx-b,如果得到的结果同时大于零或者同时小于零,说明图形的所有顶点都在直线的同侧,即直线不过图形。否则说明图形的顶点分布在直线两侧,直线过图形。
在if判断中调用了square(),triangle(),star()三个函数,以square()为例
square.m
function isThrough1=square(x1,x2,y1,y2,p1,p2)
%判断两点连线是否与正方形相交
flag1 = getline(x1,x2,y1,y2,p1(1),p2(1));
flag2 = getline(x1,x2,y1,y2,p1(2),p2(2));
flag3 = getline(x1,x2,y1,y2,p1(3),p2(3));
flag4 = getline(x1,x2,y1,y2,p1(4),p2(4));
if((flag1 >= 0 && flag2 >= 0 && flag3 >= 0 && flag4 >= 0) | (flag1 <= 0 && flag2 <= 0 && flag3 <= 0 && flag4 <= 0)) %根据原理判断连线是否与图形相交
isThrough1 = 0;%连线不与正方形相交
else
isThrough1 = 1;%连线与正方形相交
end
在square函数中,先调用了getline函数。
getline.m
function flag=getline(x1,x2,y1,y2,x,y)
%由两点得到y=kx+b形式的直线方程
k = (y2 - y1)/(x2 - x1);
b = y1;
temp = y - k * (x - x1) - b;
if temp > 0
flag = 1;
elseif temp < 0
flag = -1;
else
flag = 0;
end
getline函数主要作用是计算y-kx-b的值,并返回flag的值给square函数。
最后得到可视图:
总结可视图法步骤:
- 读取地图,手动获取顶点
- 依次遍历顶点,根据判据判断当前两个顶点的连线是否经过正方形、三角形以及五边形区域
- 若当前两个顶点的连线都不经过障碍物区域,则画出两点连线
- 循环结束,画出可视图
代码下载链接
但是我发现,我的代码好像会少画几根线,现在还没找到原因。。。水平有限,敬请指正