1. 程式人生 > 實用技巧 >MATLAB 最小包圍矩形

MATLAB 最小包圍矩形

又是計算幾何,我感覺最近對計算幾何上癮了。

當然,工作上也會用一些,不過工作上一般直接呼叫boost的geometry庫。

上次寫過最小包圍圓,這次是最小包圍矩形,要比最小包圍圓複雜些。

最小包圍矩形可不一定是個直立的矩形,也可能像下圖一樣是傾斜的。

求法如下:

1.求多邊形凸包,這裡凸包直接呼叫系統函數了,細節可以參考這裡,雖然當時寫的不怎麼樣。

2.將凸包兩個相鄰的點連線作為矩形一條邊。

3.尋找凸包上距離已得到的邊最遠的點,過該點做平行線,得到矩形第二條邊。

4.將凸包上點向已求得的邊投影,求得投影點相距最遠的兩個點,過該兩點做直線,作為矩形另外兩條邊。

5.遍歷凸包所有相鄰兩點從新執行2~4,將面積最小的矩形作為求得結果。

通常情況下,矩形會過隨機點中的5個點。

結果如下:

matlab程式碼如下:

 1 clear all;close all;clc;
 2 
 3 n=30;
 4 p=rand(n,2);
 5 
 6 ind=convhull(p(:,1),p(:,2));
 7 l=length(ind);
 8 
 9 hull=p(ind,:);          %隨機點凸包
10 
11 area=inf;
12 for i=2:l
13     p1=hull(i-1,:);     %凸包上兩個點
14     p2=hull(i,:);
15    
16     k1=(p1(2)-p2(2
))/(p1(1)-p2(1)); %連線兩點的直線,作為矩形的一條邊 17 b1=p1(2)-k1*p1(1); 18 19 d=abs(hull(:,1)*k1-hull(:,2)+b1)/sqrt(k1^2+1); %所有凸包上的點到k1,b1直線的距離 20 21 [h ind]=max(d); %得到距離最大的點距離,即為高,同時得到該點座標 22 b2=hull(ind,2)-k1*hull(ind,1); %相對k1,b1直線相對的另一條平行邊k1,b2; 23 24
k2=-1/k1; %以求得的直線的垂線斜率 25 26 b=hull(:,2)-k2*hull(:,1); %過凸包所有點構成的k2,b直線系 27 x1=-(b1-b)/(k1-k2); %凸包上所有點在已求得的第一條邊的投影 28 y1=-(-b*k1+b1*k2)/(k1-k2); 29 30 x2=-(b2-b)/(k1-k2); %凸包上所有點在已求得的第二條邊的投影 31 y2=-(-b*k1+b2*k2)/(k1-k2); 32 33 [junk indmax1]=max(x1); %投影在第一條邊上x方向最大與最小值 34 [junk indmin1]=min(x1); 35 36 [junk indmax2]=max(x2); %投影在第二條邊上x方向最大與最小值 37 [junk indmin2]=min(x2); 38 39 w=sqrt((x1(indmax1)-x1(indmin1))^2+(y1(indmax1)-y1(indmin1))^2); %矩形的寬 40 41 if area>=h*w %使面積最小 42 area=h*w; 43 pbar=[x1(indmax1) y1(indmax1); %矩形四個角點 44 x2(indmax2) y2(indmax2); 45 x2(indmin2) y2(indmin2); 46 x1(indmin1) y1(indmin1)]; 47 end 48 end 49 pbar(5,:)=pbar(1,:); 50 51 hold on; 52 plot(p(:,1),p(:,2),'.'); 53 plot(pbar(:,1),pbar(:,2),'r') 54 axis equal;