又是計算幾何,我感覺最近對計算幾何上癮了。
當然,工作上也會用一些,不過工作上一般直接調用boost的geometry庫。
上次寫過最小包圍圓,這次是最小包圍矩形,要比最小包圍圓復雜些。
最小包圍矩形可不一定是個直立的矩形,也可能像下圖一樣是傾斜的。
求法如下:
1.求多邊形凸包,這里凸包直接調用系統函數了,細節可以參考這里,雖然當時寫的不怎么樣。
2.將凸包兩個相鄰的點連線作為矩形一條邊。
3.尋找凸包上距離已得到的邊最遠的點,過該點做平行線,得到矩形第二條邊。
4.將凸包上點向已求得的邊投影,求得投影點相距最遠的兩個點,過該兩點做直線,作為矩形另外兩條邊。
5.遍歷凸包所有相鄰兩點從新運行2~4,將面積最小的矩形作為求得結果。
通常情況下,矩形會過隨機點中的5個點。
結果如下:
matlab代碼如下:
clear all;close all;clc; n=30; p=rand(n,2); ind=convhull(p(:,1),p(:,2)); l=length(ind); hull=p(ind,:); %隨機點凸包 area=inf; for i=2:l p1=hull(i-1,:); %凸包上兩個點 p2=hull(i,:); k1=(p1(2)-p2(2))/(p1(1)-p2(1)); %連接兩點的直線,作為矩形的一條邊 b1=p1(2)-k1*p1(1); d=abs(hull(:,1)*k1-hull(:,2)+b1)/sqrt(k1^2+1); %所有凸包上的點到k1,b1直線的距離 [h ind]=max(d); %得到距離最大的點距離,即為高,同時得到該點坐標 b2=hull(ind,2)-k1*hull(ind,1); %相對k1,b1直線相對的另一條平行邊k1,b2; k2=-1/k1; %以求得的直線的垂線斜率 b=hull(:,2)-k2*hull(:,1); %過凸包所有點構成的k2,b直線系 x1=-(b1-b)/(k1-k2); %凸包上所有點在已求得的第一條邊的投影 y1=-(-b*k1+b1*k2)/(k1-k2); x2=-(b2-b)/(k1-k2); %凸包上所有點在已求得的第二條邊的投影 y2=-(-b*k1+b2*k2)/(k1-k2); [junk indmax1]=max(x1); %投影在第一條邊上x方向最大與最小值 [junk indmin1]=min(x1); [junk indmax2]=max(x2); %投影在第二條邊上x方向最大與最小值 [junk indmin2]=min(x2); w=sqrt((x1(indmax1)-x1(indmin1))^2+(y1(indmax1)-y1(indmin1))^2); %矩形的寬 if area>=h*w %使面積最小 area=h*w; pbar=[x1(indmax1) y1(indmax1); %矩形四個角點 x2(indmax2) y2(indmax2); x2(indmin2) y2(indmin2); x1(indmin1) y1(indmin1)]; end end pbar(5,:)=pbar(1,:); hold on; plot(p(:,1),p(:,2),'.'); plot(pbar(:,1),pbar(:,2),'r') axis equal;