本文给出了Delaunay三角网格的生成算法,写本算法的本意是能利用Delaunay三角网格构成k阶最紧邻图,进而为Chameleon变色龙算法的实现打下基础,不足的地方请大家批评,具体Delaunay三角网格生成步骤请大家自行搜索,这里只给出了实现代码:
Delaunay三角网格生成主程序:
clc;
clear;
%读取数据文件,生成点矩阵
fileID = fopen('D:\matlabFile\Delaunay\Delaunay.txt');
C=textscan(fileID,'%f %f');
fclose(fileID);
%显示数组结果
%celldisp(C);
%将cell类型转换为矩阵类型,这里只假设原数据为二维属性,且是二维的坐标点
CC_init=cat(2,C{1},C{2});%用来保存初始加载的值
CC=CC_init;
%求解凸四边形
c1=C{1}+C{2};
c2=C{1}-C{2};
%min(x+y)
cmin1_id=find(c1==min(c1));
%min(x-y)
cmin2_id=find(c2==min(c2));
%max(x+y)
cmax1_id=find(c1==max(c1));
%max(x-y)
cmax2_id=find(c2==max(c2));
%将四边形的四个顶点存放至凸包集
convex=zeros(1,2);
convex=cat(1,convex,CC(cmin2_id,:));
convex=cat(1,convex,CC(cmin1_id,:));
convex=cat(1,convex,CC(cmax2_id,:));
convex=cat(1,convex,CC(cmax1_id,:));
convex(1,:)=[];
%将上述四个点从原始点集中去除
id_list=cmin1_id;
id_list=cat(1,id_list,cmin2_id);
id_list=cat(1,id_list,cmax1_id);
id_list=cat(1,id_list,cmax2_id);
CC(id_list,:)=[];
%增加起始点,使四边形闭合
convex=cat(1,convex,convex(1,:));
%%%%add other convex points
%start the loop
flag=1;
while flag
%get the count of point set 'convex'
num=size(convex,1);
%ergodic the convex
for i=1:num-1
% get slope of other points from initial set
% remeber the slope smaller than stationary points
convex_temp=zeros(1,2);
a=[62 68];
if convex(i,:)==a
end
for j=1:size(CC,1)
%compute every point with latter convex
r=RightOfLine(convex(i+1,:),convex(i,:),CC(j,:));
%compare the slopes
if ~r
convex_temp=cat(1,convex_temp,CC(j,:));
end
end
%delete first zero row
if size(convex_temp,1)==1
continue;
end
convex_temp(1,:)=[];
% the maximum of distance
max_dis=0;
% remeber the point of most long distance
point_max=zeros(1,2);
%find the most long distance of point
for k=1:size(convex_temp,1)
dis=ComputeDistance(convex(i+1,:),convex(i,:),convex_temp(k,:));
if dis>max_dis
max_dis=dis;
point_max=convex_temp(k,:);
end
end
%insert the point into convex set
if point_max~=zeros(1,2)
convex=[convex(1:i,:);point_max;convex(i+1:num,:)];
%delete the point_max from the initial set
for j=1:size(CC,1)
if CC(j,:)==point_max
CC(j,:)=[];
break;
end
end
break;
end
end
if size(convex_temp,1)==1&&i==num-1
flag=0;
end
end
% %plot the figure
% plot(convex(:,1),convex(:,2));
% hold on
scatter(convex(:,1),convex(:,2),'filled');
%显示初始分布图
hold on
scatter(CC(:,1),CC(:,2),'filled');
hold on
%delete last point
convex(size(convex,1),:)=[];
%%%convex hull triangulation
%store the convex hull triangles
triangles=zeros(3,2,1);
% the stopping mark
flag=1;
while flag
% if the size of convex hull is below three, the loop should be stop
if size(convex,1)<3
break;
end
for i=1:size(convex,1)-2
p=convex(i:i+2,:);
% delete the three points
convex_residual=convex;
convex_residual(i:i+2,:)=[];
%judge if the residual convex hull in the circumcircle of p(triangle)
result=PointInCircle(p,convex_residual);
if ~result
%add p into triangles set
triangles(:,:,size(triangles,3)+1)=p;
%delete the mid point at p from convex set
convex(i+1,:)=[];
% complete the for loop
break;
end
end
% if there is only three points, the loop will be stop, and add the
% last three points into triangles set
if size(convex,1)==3
triangles(:,:,size(triangles,3)+1)=convex;
flag=0;
end
end
%delete the first row
triangles(:,:,1)=[];
%plot all the triangles
% for i=1:size(triangles,3)
% p=triangles(:,:,i);
% p=cat(1,p,p(1,:));
% plot(p(:,1),p(:,2));
% hold on
% end
% the next step is interpolating discrite point
%insert every point and reconstruct the triangles set
for i=1:size(CC,1)
triangles=PointInCircumCircle(CC(i,:),triangles);
end
%plot all the triangles
for i=1:size(triangles,3)
p=triangles(:,:,i);
p=cat(1,p,p(1,:));
plot(p(:,1),p(:,2));
hold on
end
title('Delaunay');
CircumCircle函数实现过程:
function result=CircumCircle(p)
% consider if there are two y is equal,if equal,then resequence the points in p
if p(1,2)==p(2,2)
p1=[p(1,:);p(3,:);p(2,:)];
p=p1;
end
if p(2,2)==p(3,2)
p1=[p(2,:);p(1,:);p(3,:)];
p=p1;
end
cen1=(p(1,:)+p(2,:))/2; %三角形一条边中点
cen2=(p(2,:)+p(3,:))/2; %另一条边中点
k1=-1/((p(1,2)-p(2,2))/(p(1,1)-p(2,1))); %一条边垂直平分线
b1=cen1(2)-k1*cen1(1);
k2=-1/((p(2,2)-p(3,2))/(p(2,1)-p(3,1))); %另一条边垂直平分线
b2=cen2(2)-k2*cen2(1);
x0=-(b1-b2)/(k1-k2); %求两直线交点
y0=-(-b2*k1+b1*k2)/(k1-k2);
R=sqrt((y0-p(1,2))^2+(x0-p(1,1))^2);
result=cat(1,x0,y0);
result=cat(1,result,R);
CommonEdges函数实现如下:
function result=CommonEdges(p,triangles)
%define zeros edges array in order to store the common edges
edges=zeros(2,2,1);
%ergodic the triangles set
for i=1:size(triangles,3)
%extract one triangle(composed with three points) and construct three
%edges
triangle=triangles(:,:,i);
for j=1:3
if j==3
edge=[triangle(1,:);triangle(3,:)];
else
edge=[triangle(j,:);triangle(j+1,:)];
end
% sort the matrix 'edge'
edge=sortrows(edge);
% add edge into edges set
edges(:,:,size(edges,3)+1)=edge;
end
end
%delete first zero dimension
edges(:,:,1)=[];
%store the serial number in order to delete common edges at final time
serial_num=zeros(1,1);
for i=1:size(edges,3)-1
% first edge
a=edges(:,:,i);
for j=i+1:size(edges,3)
% second edge
b=edges(:,:,j);
%compare the two edges, if equal, then delete the edge from
%edges set and break two 'for' loop, restart 'while' loop
if isequal(a,b)
%save the numbers
serial_num=cat(1,serial_num,i);
serial_num=cat(1,serial_num,j);
break;
end
end
end
%delete first row
serial_num(1,:)=[];
edges(:,:,serial_num)=[];
%reconstruct all triangles
triangles_new=zeros(3,2,1);
for i=1:size(edges,3)
%extract one edge
edge=edges(:,:,i);
%add the third convex,reconstuct triangle
edge=cat(1,edge,p);
%add new triangle into new triangles set
triangles_new(:,:,i)=edge;
end
result=triangles_new;
end
ComputeDistance函数实现如下:
function result=ComputeDistance(c,b,a)
format short
ab=sqrt((a(1,1)-b(1,1))^2+(a(1,2)-b(1,2))^2);
ac=sqrt((a(1,1)-c(1,1))^2+(a(1,2)-c(1,2))^2);
bc=sqrt((c(1,1)-b(1,1))^2+(c(1,2)-b(1,2))^2);
cos_theta=(ab^2+bc^2-ac^2)/(2*ab*bc);
result=ab*sqrt(1-cos_theta*cos_theta);
end
ComputeSlope函数实现如下:
function result=ComputeSlope(fPoint,lPoint)
if (fPoint(1,1)-lPoint(1,1))==0
result=100000000;
else
result=(fPoint(1,2)-lPoint(1,2))/(fPoint(1,1)-lPoint(1,1));
end
end
Optimizing函数实现如下:
function result=Optimizing(triangles)
%find common edge between every adjacent triangles, and optimizing them.
%we should test every edge of every triangle, and judge that if there is
%another edge is exist
% set a flag of while
flag=1;
while flag
for i=1:size(triangles,3)-1
%extract one triangle
triangle=triangles(:,:,i);
% ergodic every edge of the triangle
flag_1=0;
for j=1:3
if j==3
edge=[triangle(1,:);triangle(3,:)];
else
% extract two points of triangles and construct edge
edge=triangle(j:j+1,:);
end
%add a zero row in order to use 'itersect' function
edge=cat(1,edge,[0 0]);
%ergodic the rest of triangles set and find the common edge
flag_2=0;
for k=i+1:size(triangles,3)
triangle_1=triangles(:,:,k);
%intersect the edge with current triangle
[edge_temp,ia,ib]=intersect(triangle_1,edge,'rows');
%resequence the edge point in order to compare the edge
edge_noZero=sortrows(edge);
edge_noZero(1,:)=[];
edge_temp=sortrows(edge_temp);
% if there is a common edge
if isequal(edge_noZero,edge_temp)
%compute the center and radius of circumcircle of
%triangle
circle=CircumCircle(triangle);
% obtain the fouth convex of polygon
convex=triangle_1;
convex(ia,:)=[];
% if point in circumcircle
dis=sqrt((convex(1,1)-circle(1,1))^2+(convex(1,2)-circle(2,1))^2);
if dis<=circle(3,1)
%find the other convex of triangle
[edge_temp_1,ia2,ib2]=intersect(triangle,edge,'rows');
convex_1=triangle;
convex_1(ia2,:)=[];
%reconstruct the two triangles
triangle_new1=[edge(1,:);convex;convex_1];
triangle_new2=[edge(2,:);convex;convex_1];
%replace the initial two triangles from triangles
triangles(:,:,k)=triangle_new1;
triangles(:,:,i)=triangle_new2;
%stop all levels loop,restart the 'while' loop
flag_2=1;
flag_1=1;
break;
end
end
end
if flag_2
break;
end
end
if flag_1
break;
end
end
if i==size(triangles,3)-1
break;
end
end
result=triangles;
end
PointInCircle函数实现如下:
function result=PointInCircle(p,convex_residual)
%compute the radius of circumcircle
f=CircumCircle(p);
%compute the distance between the center of circle and residual convex
%points
flag=0;
for i=1:size(convex_residual,1)
%compute the distance between two points
dis=sqrt((f(1,1)-convex_residual(i,1))^2+(f(2,1)-convex_residual(i,2))^2);
if dis<=f(3,1)
flag=1;
break;
end
end
result=flag;
end
PointInCircumCircle函数实现如下:
function result=PointInCircumCircle(p,triangles)
%store the triangle which contain the inter point
triangles_in=zeros(3,2,1);
%%compute the circumcircle of each triangle in triangles set
%remeber the sequence of trangle that satisfy the condition
id=zeros(1,1);
for i=1:size(triangles,3)
%compute radius and center point of circumcircle
c=CircumCircle(triangles(:,:,i));
%compare the distance between p and the center with radius
dis=sqrt((c(1,1)-p(1,1))^2+(c(2,1)-p(1,2))^2);
%if dis smaller than radius,store the triangle into inPoints and
%delete this triangle from triangles
if dis<=c(3,1)
triangles_in(:,:,size(triangles_in,3)+1)=triangles(:,:,i);
id=cat(1,id,i);
end
end
%delete first row of id
id(1,:)=[];
%delete all triangles from triangles set that satisfy the condition
triangles(:,:,id)=[];
triangles_in(:,:,1)=[];
%%% reconstruct the triangle from triangles_in set
%if the size of triangle_in is 1,then we can add three triangles into
%triangles set directly
if size(triangles_in,3)==1
%initial triangle
tri=triangles_in(:,:,1);
%the new three triangles
tri1=cat(1,tri(1:2,:),p);
tri2=cat(1,tri(2:3,:),p);
tri3=cat(1,tri(1,:),tri(3,:));
tri3=cat(1,tri3,p);
triangles(:,:,size(triangles,3)+1)=tri1;
triangles(:,:,size(triangles,3)+1)=tri2;
triangles(:,:,size(triangles,3)+1)=tri3;
else
%delete common edges of all triangles in triangles_in set
triangles_in=CommonEdges(p,triangles_in);
m=size(triangles,3);
n=size(triangles_in,3);
triangles(:,:,m+1:m+n)=triangles_in;
%%this is a wrong way to reconstruct triangle through vertexes
%%rearrange
%find the common edge in triangles_in, and delete it, and insert new
%triangles
%%%%% notice: here, we only find all vertexes of triangles
% vertexes=zeros(1,2);
% for i=1:size(triangles_in,3)
% tri=triangles_in(:,:,i);
% vertexes=cat(1,vertexes,tri);
% end
% % delete the same value rows
% vertexes(1,:)=[];
% vertexes=unique(vertexes,'rows');
% % resort the vertexes, and order the vertex anti-clockwise
% vertexes=SortVertexes(vertexes);
% %add first point, and close the circle
% vertexes(size(vertexes,1)+1,:)=vertexes(1,:);
% %reconstruct the triangles set
% for i=1:size(vertexes,1)-1
% tri=cat(1,vertexes(i,:),vertexes(i+1,:));
% tri=cat(1,tri,p);
% triangles(:,:,size(triangles,3)+1)=tri;
% end
end
result=triangles;
%find common edge between every two adjacent triangles, and optimized
%triangles set
%result=Optimizing(triangles);
end
RightOfLine函数实现如下:
function result=RightOfLine(p1,p2,p)
% (y1 – y2) * x + (x2 – x1) * y + x1 * y2 – x2 * y1
%(x2-x1)(y0-y1)-(y2-y1)(x0-x1)
% flag=(p1(1,2)-p2(1,2))*p(1,1)+(p2(1,1)-p1(1,1))*p(1,2)+p1(1,1)*p2(1,2)-p2(1,1)*p1(1,2);
flag=(p2(1,1)-p1(1,1))*(p(1,2)-p1(1,2))-(p2(1,2)-p1(1,2))*(p(1,1)-p1(1,1));
if flag<0
result=1;
else
result=0;
end
% tmpx=(p1(1,1)-p2(1,1))/(p1(1,2)-p2(1,2))*(p(1,2)-p2(1,2))+p2(1,1);
% %当tmpx>p.x的时候,说明点在线的左边,小于在右边,等于则在线上。
% if (tmpx < p(1,1))
% result=1;
% else
% result=0;
% end
end
SortVertexes函数实现如下:
function result=SortVertexes(vertexes)
%the final ordered vertexes
vertexes_final=zeros(1,2);
%find the minimum y in vertexes
ymin=min(vertexes);
%count the yValue which is minimum
ymin=find(vertexes(:,2)==ymin(1,2));
% if there are more than 1 minimum values, you should find the min x
if length(ymin)>1
vertex_temp=vertexes(ymin,:);
xmin=min(vertex_temp(:,1));
xmin=find(vertex_temp(:,1)==xmin(1,1));
vertexes_final(1,:)=vertex_temp(xmin(1,1),:);
%delete the vertex from vertexes set
for i=1:size(vertexes,1)
if vertexes(i,:)==vertex_temp(xmin(1,1),:)
vertexes(i,:)=[];
break;
end
end
else
vertexes_final(1,:)=vertexes(ymin(1,1),:);
%delete the vertex from vertexes set
vertexes(ymin(1,1),:)=[];
end
% sort other vertesex
%store the polar angle
polarAngle=zeros(1,2);
for i=1:size(vertexes,1)
pAngle=atan2(vertexes(i,2)-vertexes_final(size(vertexes_final,1),2),vertexes(i,1)-vertexes_final(size(vertexes_final,1),1));
if pAngle<0
pAngle=pAngle+pi;
end
polarAngle=cat(1,polarAngle,[pAngle,i]);
end
polarAngle(1,:)=[];
polarAngle=sortrows(polarAngle,1);
% resort the order of vertexes set depending on polar angle
for i=1:size(polarAngle,1)
vertexes_final(size(vertexes_final,1)+1,:)=vertexes(floor(polarAngle(i,2)),:);
end
% %find the minimum polar angle,if there are more than 1 minimum, then
% %you should comare the distance,which is mimimum.
% polarA_min=find(polarAngle(:,1)==min(polarAngle));
% if size(polarA_min,1)>1
% minDis=100000000000;
% x0=vertexes_final(size(vertexes_final),1);
% y0=vertexes_final(size(vertexes_final),2);
% % remeber the minimum distance order in vertexes
% num=0;
% %compute the distance of vertexes
% for i=1:size(polarA_min,1)
% x=vertexes(polarA_min(i,1),1);
% y=vertexes(polarA_min(i,1),2);
% dis=sqrt((x0-x)^2+(y0-y)^2);
% if dis