ToLeft 測試與計算凸包問題

2021-08-21 11:54:22 字數 2374 閱讀 6232

求解計算幾何中的凸包問題時,使用的比較簡單,但是複雜度比較高的演算法中有一種演算法叫做極點法,基本思想是從所有的點中去除所有的不是凸包邊上的點.

從所有的剩餘的點中,選出三個點,然後再在剩餘的點集中,判斷是否在三角形的內部,如果在內部,則去除這個點,說明它不是凸包的結果;否則,就暫時保留這個點,說明它可能是凸包邊上的點.如下圖所示:點a在三角形的內部,肯定不是凸包上的點,點b暫時可能是凸包上的點.

不難從上面的圖中看出,若把三角形的三個邊都設定為逆時針方向,那麼點a在三個向量邊的左側.b在其中兩條邊的左側,但是在p和q那條邊的右側.

由此可以判斷,當乙個點在三角形三條逆時針邊的左側時,點必定在三角形的內部,不是凸包邊上的解,否則不是在三角形內部.這就是所謂的toleft測試.

實現toleft測試方法也有很多,最經典的是使用求解矩陣行列式求解有向面積的方式.

設兩個點p和q,測試點s是在pq連線的左側還是右側,如下圖所示.

讓p, q,s構成乙個三角形,然後各個邊,邊的方向與pq的方向一致,這個三角形的有向面積計算如下: 2∗

s=∣∣

∣∣∣p

[x]q

[x]s

[x]p

[y]q

[y]s

[y]p

[z]q

[z]s

[z]∣

∣∣∣∣

2 ∗s

=|p[

x]p[

y]p[

z]q[

x]q[

y]q[

z]s[

x]s[

y]s[

z]|這樣的乙個行列式的計算過程只有乘法和加減法,避免了使用除法或者其他的三角函式計算.寫成**形式就更簡單了.

int area2(point p, point q, point k)

上面的**只是計算有向面積,toleft測試是判斷是否在直線的左側,當這個有向面積大於0的時候,在左側,當小於0的時候,在右側,當等於0 的時候,三點一線,面積為0.

bool toleft(point p, point q, point s)

回頭想一下,這裡其實符合右手定理.

參考鄧老師的課件,根據toleft測試,實現乙個計算凸包的演算法,雖然計算複雜度是o(n^4),但是也是一種解法,下面是實現的乙個**.

#include 

#include

using

namespace

std;

struct point

int _x;

int _y;

};int area2(point p, point q, point s)

bool toleft(point p, point q, point s)

int main()

, ,,,

,};vector

flag(points.size(), false);

for (int i = 0; i < points.size(); ++i)}}

}for (int i = 0; i < points.size(); ++i)

return

0;}

極邊法要比極點法快一點,時間複雜度是o(n^3).

#include 

#include

#include

using

namespace

std;

struct point

int _x;

int _y;

};int area2(point p, point q, point s)

bool toleft(point p, point q, point s)

int main()

, ,,,

,};vector

flag (points.size(), false);

for (int i = 0; i < points.size(); ++i)

if (leftnotempty == false || rightnotempty == false)}}

for(int i = 0; i< flag.size();++i)

return

0;}

計算幾何 凸包問題

給定平面上的二維點集,求解其凸包。一 graham掃瞄法 1.在所有點中選取y座標最小的一點h,當作基點。如果存在多個點的y座標都為最小值,則選取x座標最小的一點。座標相同的點應排除。然後按照其它各點p和基點構成的向量與x軸的夾角進行排序,夾角由大至小進行順時針掃瞄,反之則進行逆時針掃瞄。實現中無需...

計算幾何 凸包

有多個手機訊號發射器,求解乙個最小區域,要求所有的發射器都包含在這個最小區域中,並且任意兩台發射器之間的交流包含於在這個區域內。將所有的發射器看做為點,任意兩個點之間的連線都包含於乙個平面s 乙個平面的子集s 是凸的,當且僅當 s中的任意兩個點之間的連線都包含於 s中。點集 p的凸包是所有包含 p的...

計算幾何 凸包

如求凸包周長 include include include include include include using namespace std define pi 3.1415926 define eps 1e 10 class point 建立point類,裡面包含很多point的運算子 定...