Jarvis’ March 圖示
先從一個凸包上的頂點開始,順着外圍繞一圈。
每當尋找下一個要被包圍的點,則遍歷平面上所有點,找出最外圍的一點來包圍。可以利用叉積運算來判斷。
- 時間複雜度爲 O(NM) , N 爲所有點的數目, M 爲凸包的頂點數目。
具體思想:
- 先確定邊界上的點v1和與下一個點v2
- 在點集裏去尋找下一個點v3,使得v1 v3 v2滿足CCW
- 如果滿足,這就說明v3是更外圍的點
- 把v3的值覆蓋v2,即v2 = v3
- 重複的3步,直到所有點都訪問過,即爲找到了下一個最外邊的點
- 將v2的值覆蓋v1,即v1 = v2
- 重複第2步,直到下一個點回到起點
CCW:counterclockwise 以逆時針方向旋轉
Jarvis’ March 代碼
typedef vector<pair<double, double>> vpdd;
typedef pair<double, double> pdd;
bool ccw(pdd a, pdd b, pdd c)
{
return ((c.first - a.first) * (b.second - a.second) - (c.second - a.second) * (b.first - a.first)) < 0;
}
void jarvis_march(const vpdd &input)
{
int n = input.size();
int left = 0;
for (int i = 0; i < n; i++)
{
if (input[i].first < input[left].first)
{
left = i;
}
}
int first_point = left;
int third_point;
do
{
hull_jmarch.push_back(input[first_point]);
// cout<<"here\n";
third_point = (first_point + 1) % n;
for (int i = 0; i < n; i++)
{
if (ccw(input[first_point], input[i], input[third_point]))
{
third_point = i;
}
}
first_point = third_point;
} while (first_point != left);
}