2D凸包算法(一):Jarvis' March ( Gift Wrapping Algorithm )

Jarvis’ March 圖示

在這裏插入圖片描述

先從一個凸包上的頂點開始,順着外圍繞一圈。
每當尋找下一個要被包圍的點,則遍歷平面上所有點,找出最外圍的一點來包圍。可以利用叉積運算來判斷。

  • 時間複雜度爲 O(NM) , N 爲所有點的數目, M 爲凸包的頂點數目。

在這裏插入圖片描述

具體思想:

  1. 先確定邊界上的點v1和與下一個點v2
  2. 在點集裏去尋找下一個點v3,使得v1 v3 v2滿足CCW
  3. 如果滿足,這就說明v3是更外圍的點
  4. 把v3的值覆蓋v2,即v2 = v3
  5. 重複的3步,直到所有點都訪問過,即爲找到了下一個最外邊的點
  6. 將v2的值覆蓋v1,即v1 = v2
  7. 重複第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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章