Delaunay三角网格生成

本文给出了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










你可能感兴趣的:(数据挖掘)