日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法 判断多个点是否在同一圆周线上_凸包问题——礼物包裹算法

發布時間:2024/9/30 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法 判断多个点是否在同一圆周线上_凸包问题——礼物包裹算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

禮物包裹算法最早由Chand&Kapur (1970) [1]提出的,它不僅可以實現二維、三維凸包,還可以實現更高維的凸包,算法復雜度是

,表示輸出的面的數量,表示點集的個數,算法復雜度跟輸出面相關。直觀上,三維的禮物包裹算法,可以看做是在點集的外面包圍了一張紙,每次更新一個新的頂點,用紙覆蓋住它,就像包裹禮物一樣,直至覆蓋整個點集。本篇只考慮三維的凸包求解問題,對于更高維的情況,可以參考Chand&Kapur (1970) [1]以及Preparata&Shamos (1985) [2]的描述。

本篇文章主要介紹三維禮物包裹算法來求點集的三維凸包。

文章目錄

  • 基本思想
  • 退化情況
  • 算法實現
  • 源碼實現
  • 參考

基本思想

禮物包裹算法基于一個簡單的理論:任意一個三維凸包的每一條邊有且只有兩個相鄰面。三維凸包上的每個面用三角形面片表示,若一個凸包有

個面,則凸包共有條邊,根據歐拉公式可知,頂點的個數是。 設三維凸包上的面用三角形面片表示,這里暫不考慮各種退化情況,三維凸包的禮物包裹算法的算法偽碼如下所示:三維空間下點集的凸包
  • 面集合為Q,存儲邊的集合;
  • ;
  • ;
  • 找到一個初始的凸包面;
  • ;
  • 面的每條邊信息和計數器;????//計數器初始值為1
  • while( 非空 )
  • ????令;
  • ????for 面的每一條邊, then
  • ????????根據邊,從集合中檢索出相應的邊結構;
  • ????????if , then
  • ????????????以邊為邊界,找到新的面;
  • ????????????令;
  • ????????????更新邊集合;?// 若面的邊存儲在集合中,對應邊的計數器值加 1; 否則,創建新的邊結構,存入集合中,初始計 數器的值為1;
  • ????????end if;
  • ????end for;
  • end while;
  • 實現禮物包裹算法時,必需解決算法中要處理的三個關鍵的子問題:

  • 如何存儲邊結構的集合。
  • 給定一個凸包上的面,如何確定與該面片上任意一條邊相鄰的三角形面片;
  • 如何確定在凸包上的初始三角形面片;
  • 子問題1

    如何設計存儲邊的集合的

    數據結構。

    首先,確定兩點大小關系的對比規則,設兩點

    和,若,當且僅當;若,當且僅當;否則,和,若,當且僅當;若,當且僅當;否則,

    接著,考慮存儲邊的數據結構的設計,每個邊結構表示為

    ,其中表示邊的兩個端點,記錄與邊相鄰面的個數,通過計數器可以判定與該邊是否存在相鄰面,因為凸包上的每一條邊當且僅當有2個相鄰面。

    把邊結構存儲在一個平衡二叉樹的數據結構中,邊結構的查詢、插入操作只需要

    ,其中表示邊的個數。

    子問題2

    給定一個凸包上的三角形面片,如何確定與該面片上任意一條邊相鄰的三角形面片。

    圖1. 指定三角形是可以確定一個平面,不同的點與三角的某條邊有不同的夾角

    設三個點

    形成的三角形是凸包上的面片,三個點所在的平面是,從點集中到找一個點,使得由點,和形成的平面與平面的夾角最大,那么由點與邊生成的三角形面片即是凸包的面。以圖1所示為例,點,,,與邊分別可以確定四個平面,這四個平面與平面有一個夾角,選擇夾角最大的平面,即由點與邊確定的平面,因此生成的三角形面片是凸包上的面。

    圖2. 計算由點pi,p0,p1確定的面,與另一個平面的夾角

    在介紹了采用的策略后,接下來介紹如何實施策略,即如何判斷哪個點與三角形面片確定的平面

    與平面之間的夾角最大。如圖2所示,設平面的法向量是,若三角形點的順序如該圖所示,則法向量為,即,方向為垂直于平面向上。因為在凸包上,所以對于任意一個點(),都在平面上(On the plane)或者平面的上方空間(Above the plane)。

    圖3. 計算經過點pi和邊p0-p1面的法向量

    指定一個方向向量

    ,令同時垂直于法向量和邊,則向量,即有。點在所在的方向上。連接點和點,得到向量,計算在法向量和向量方向上的投影,分別是和,則對于不在平面上的點的夾角可以用等式(1)表示:

    遍歷點集上的每個點,選擇

    值最大的點,就要所求的點,即:

    由點

    向點方向觀察圖2,可以得到橫截面如圖3所示,設是由點,,確定的平面的法向量,向量是向量在如圖3所示的橫截面上的投影,易知向量與法向量垂直。設在方向上的投影為,在方向上的投影為,由相似三角形的性質可得:

    那么法向量

    的方向可以表示為

    可以注意到,我們只需要找到

    值最大的點,并不關心具體的值是多少,因此在計算向量和,可以不對它們進行歸一化處理,即。未歸一化的向量和也不會對等式(4)中法向量的方向造成影響,讀者可以自行證明。確定值最大的點需要遍歷點集,算法的復雜度為。

    子問題3

    如何確定在凸包上的初始三角形面片。

    算法的起始階段,先排除點集中重復的點,找到初始的凸包面

    ,如圖4所示,從點集中找到最小的點,即點的分量最小,若分量最小的點有多個,則取其中分量最小的點,若分量最小的點有多個,則取其中分量最小的點。最小的點是唯一的,經過點作一個平面,平面的法向量表示為,任取一個向量,遍歷點集上的點,使用等式(1)計算得到最大的點,設該點是。采用等式(4),計算出平面的法向量,其中,易知法向量是的形式,第3個分量為0。接著,指定一個與法向量和邊垂直的向量,可以采用等式來計算。遍歷點集上的點,使用等式(2)計算出最大的點,設該點是。至此,初始凸包上的三角形面片的三個點都計算出來了,算法需要三次遍歷點集,算法規模是。

    圖4. 在凸包上的初始三角形面片p0-p1-p2

    綜上,在禮物包裹算法中,確定初始的三角形面片,需要時間

    ;每確定一個新的凸包面,需要時間,其中表示邊,又,即時間復雜度為。因此,三維禮物包裹算法的時間復雜度為。

    退化情況

    多點共面

    如果算法實現中,沒有考慮多點共面的情況,會引起錯誤。如圖5所示,求與平面

    上邊相鄰在面,得到平面的夾角最大,但是在平面上,存在4個或者大于4個點,圖中有7個點在平面。若隨機地選擇一個點來更新平面F',可能會選擇點,也可能是點,但是顯然點不是凸包的極點,就引發了錯誤。若選擇與邊距離最遠的點來更新平面F',就會選擇點,它一定是凸包上的極點,但可能會引發生成的面的邊可能會發生交叉的情況。如圖9.15所示,考慮邊的相鄰面,最遠點是,連接3點得到凸包上的面;接著考慮邊的相鄰面,最遠點是,連接3點得到凸包上的另外一個三角形面片,這就造成了邊發生相交的情況。

    圖5. 多個點共面的情況

    這里介紹一種方法,設三維空間上的點集

    在同一個平面上,把點集投影到二維空間上,得到新的點集。三維點投影到二維空間上,可以采用的方法是:設點集所在的平面的法向量為,移除法向量的絕對值最大的分量,即對于任意一個點,投影后的點如等式(9.11)所示。

    使用二維凸包算法,求出點集

    的凸包,設求出的二維凸包為,那么三維點構成的對應的凸多邊形為,其中,點是點在二維空間對應的投影點,。可以把劃分成,,...,共個三角形面片,這種方法生成的三角形面片不會發生相交的情況。以圖6為例,凸包為,就可以劃分為,,,共4個三角形面,如圖7所示。

    圖6. 選擇與邊距離最遠點更新新面,可能產生的問題

    圖7. 把凸包上的點,劃分為不相交的三角形面

    在確定凸包上的初始三角形面片時,也可能有多個點在同一個面上,此時不需將共面點集投影到二維平面上求出子凸包,只需選擇與指定邊距離最遠的點即可,該點一定是凸包的極點,避免了不必要的算法操作。

    分母為零的情況

    若所求的點

    在平面上,則在法向量方向上的投影,顯然,等式(1)的分母為零。此時,需要根據分子的符號判斷該點是否有效。若,說明該點是無效點,直接忽略;若,說明該點是有效的,則夾角最大的點在平面上。以圖8所示為例,點在平面上,在求與三角形面的邊相鄰的凸包面時,點是有效點,但是點都是無效點。

    圖8. 分母為零的情況

    算法實現

    存儲點的數據結構可以表示為{x,y,z,IsOn},其中,x,y,z分別表示點的X,Y,Z方向上的坐標,IsOn是標志位,是一個布爾數,表示指定點是否是凸包上的極點,這個數據在輸出結果時會起到作用,對于標志位為false的點可以刪除,保留下標志位為true的點。起始時,對于任意一個點

    ,p.IsOn的值都為false。

    前面介紹了邊結構可以用{p,q,count}來表示,包括邊的兩個端點p,q和相鄰面個數的記數器count。可以采用點的索引來記錄邊,減少存儲空間,因此邊結構中的p,q表示點的索引,用V表示全局點集,那么邊結構e的端點信息就是V[e.p]和V[e.q]。使用平衡二叉樹來作為存儲邊結構的容器,用T表示,邊結構的查詢、插入操作只需要

    的時間,其中,m表示邊的個數。對存儲邊結構的平衡二叉樹T的查詢和插入的表示方法如下所示:
    • T.find({p,q}),從T中檢索出以V[p],V[q]為端點的邊結構,并將它返回;
    • T.insert({p, q}),若T中存在以V[p],V[q]為端點的邊,則將相應的邊結構的count值加1;否則,創建一個邊結構{p,q,1},并把它插入T中。

    三維凸包上的面用三角形面片表示,存儲面的數據結構可以表示為{v0, v1, v2},與邊結構類似,為了減少存儲內存,v0, v1, v2表示點的索引,如果給定一個三角形面片F,則它的3個頂點信息就是V[F.v0], V[F.v1], V[F.v2]。三角形面片的朝向是固定的,我們規定,通過等式cross(V[F.v1] - V[F.v0], V[F.v2] - V[F.v0]),計算出的面片的法向量指向凸包外。 算法中還需要設計一種存儲三角形面片的容器,由于我們只需要將三角形面片插入容器首部(尾部)元素、刪除容器首部(尾部)元素、遍歷操作,所以可以采用鏈表這種數據結構作為存儲三角形面片的容器。一方向可以用于存儲候選三角形面片;另一方面用于存儲求出的凸包面片,最終作為結果輸出。對鏈表數據結構List主要的操作的表示方法如下所示:

    • List.push(O),把元素O插入鏈表List內;
    • List.pop(),從鏈表List中彈出一個元素,并將它返回;

    下面給出算法的偽碼,考慮到了輸入的點集存在重合或在同一個平面上,以及上一節描述的多點共面、分母為零的情況。

    采用禮物包裹算法求三維空間下點集的凸包
    giftWrapping(S)
  • ????對點集S中的點從小到大排序;
  • ????移除點集S中重復的點,得到新的點集;
  • if || 點集共面, then
  • ????return 空集;
  • end if;
  • Z = 空集;????????????????????????????????????// Z存儲用于輸出的面片,鏈表
  • Q = 空集;????????????????????????????????????// Q存儲候選面片,鏈表
  • T = 空集;????????????????????????????????????// T存儲邊結構,平衡二叉樹
  • F = initFirstFacet(V);
  • T.insert({F.v0, F.v1, 1});
  • T.insert({F.v1, F.v2, 1});
  • T.insert({F.v1, F.v0, 1});
  • Q.push(F);
  • Z.push(F);
  • while( Q非空 )
  • ????F = Q.pop();
  • ????n = -cross(V[F.v1] - V[F.v0], V[F.v2] – V[F.v0]);
  • ????for ( i=0 ; i<3 ; i+=1 )
  • ????????p = F.vi, q = F.v(i+1)%3;
  • ????????E = T.find({p, q});
  • ????????if E.count > 1, then
  • ????????????continue;
  • ????????end if;
  • ????????a = cross(n, V[p] – V[q]);
  • ????????{PS, km} = getExtremePoint(V, n, a, V[p]); // PS是一個鏈表
  • ????????d = cross(V[p] – V[q], V[km] – V[q]);
  • ????????if PS 集合數大于1, then
  • ????????????CH = degenerate(d, E, PS);
  • ????????else
  • ????????????CH = PS;
  • ????????????CH.push_front(q);
  • ????????????CH.push_front(q);
  • ????????end if;
  • ????????for each k in CH
  • ????????????V[k].IsOn = true;
  • ????????end for;
  • ????????m = CH集合個數;????????????????????????????????//凸包CH的頂點個數
  • ????????h0 = CH[0], h1 = CH[1], h2 = CH[2], h = 2;
  • ????????while(h < m)
  • ????????????T.insert({h2, h1});
  • ????????????F' = {h0, h2, h1};
  • ????????????Z.push(F');
  • ????????????Q.push(F');
  • ????????????h += 1;
  • ????????????if h == m - 1, then
  • ????????????????T.insert({h0, h2});
  • ????????????else
  • ????????????????h1 = h2;
  • ????????????????h2 = CH[h];
  • ????????????end if;
  • ????????end while;
  • ????end for;
  • end while;
  • return Z;
  • 算法第1 ~ 5步,排除點集S中重復的點、以及點集S在同一個平面上的情況。第6 ~ 17步,初始化必要的存儲結構,確定在凸包上的初始三角形面片。接著,進入while循環,從Q中取出一個候選面片F,分別處理面片F的3條邊,從T中查找到相應存儲有相應邊的邊結構E。如果E.count > 1,說明該邊已存在兩個相鄰面,不作任何處理,否則,計算出與其相鄰面的F’,將面F’的另外兩條邊插入到平衡二叉樹T中。

    函數getExtremePoint ()實現的功能是:給定一個凸包上的面F,確定與面片F上的邊E相鄰的三角形面片,PS表示一個點的索引集合,因為有可能與E相鄰的三角形面片所在的平面上有多個點,即前面敘述的多點共面的情況,km表示PS中與邊E距離最遠的點的索引。

    函數initFirstFacet()實現的功能是:確定在凸包上的初始三角形面片。

    函數degenerate ()實現的功能是:解決多點共面這種退化情況,把三維的點

    投影到二維空間上,再根據二維凸包算法計算出凸多邊形,最后把結果返回。可以確定,函數degenerate()需要確保凸多邊形CH是單一個方向。三維點投影到二維,以及求二維凸包算法,在前面都已詳細介紹,這里不再贅述算法。

    圖9. 禮物包裹算法過程

    最后,以圖9所示為例來演示禮物包裹算法giftWrapping(S)的流程,可以結合偽碼,模擬下算法的過程。圖中的點集為

    ,分布在一個2x2x2的矩形方塊上,點集的坐標如表1所示。禮物包裹算法會先確定一個初始的三角形面片,設為,把面片存入Q和Z。接著,進入while循環,從Q中取出第1個面片,先處理面片上的邊,產生新的面片;再處理邊,此時出現多點共面的情況,點與邊共面,且產生的夾角最大,隨機啟動“多點共面情況”的子算法,最終產生兩個面片和;最后處理邊,產生新的面片。在處理完第1個三角形面片后,候選面片集。由于Q非空,第2次進行while循環內的迭代操作,處理面片,先處理邊,生成新的面片;再處理邊,生成;最后處理邊,由于該邊的兩鄰面個數為2,已不存在其它相鄰面,不作處理,此時候選面片集。由于Q非空,從中取出一個平面,重復上述操作,直至Q為空,輸出三維凸多邊體的面片,算法結束。如表1所示,由于篇幅限制,只記錄了前4個面片的處理結果。

    表1. 點集坐標和算法循環體內的處理結果

    源碼實現

    基礎庫源碼鏈接,參見這里,下面是前面所描述的算法的實現。

    #define _CRTDBG_MAP_ALLOC

    參考

    [1] Donald R. Chand, and Sham S. Kapur. "An algorithm for convex polytopes."Journal of the ACM (JACM), vol.17, no.1, pp.78-86, 1970.

    [2] Franco P. Preparata, and Michael Ian Shamos. Computational geometry. an introduction. Texts and Monographs in Computer Science, New York: Springer, 1

    總結

    以上是生活随笔為你收集整理的算法 判断多个点是否在同一圆周线上_凸包问题——礼物包裹算法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。