一,演算法原理
以上圖為例,直線(start,end)切割凹多邊形abcdefghijklmnop。
記切割線divline=(start,end)。
多邊形頂點序列vertexlist=(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)。
邊序列edgelist=(ab,bc,cd,de,ef,fg,gh,hi,ij,jk,kl,lm,mn,no,op,pa)。
下面開始計算:
1,求切割點。
遍歷edgelist,拿其中各edge與divline求交,得切割點序列divpointlist=(1,2,3,4,5,6,7,8)。
注:線段與直線求交,見:
插入切割點後頂點序列vertexlist_afterdiv=(a,1,b,c,2,d,e,3,f,g,4,h,i,5,j,k,6,l,m,7,n,o,8,p)。
插入切割點後的邊序列edgelist_afterdiv=(a1,1b,bc,c2,2d,de,e3,3f,fg,g4,4h,hi,i5,5j,jk,k6,6l,lm,m7,7n,no,o8,8p,pa)。
2,求各邊在切割線哪一側。
所謂「點在切割線左側」是指:當站在start面朝end時,點在左手邊。
可以使用點到直線的帶符號距離來判斷點在直線的哪一側,參考:
求得結果為:b,c,f,g,j,k,n,o在切割線右側,a,d,e,h,i,l,m,p在切割線左側。
則切割後的邊集edgelist_afterdiv被劃分為兩個集合:
右側邊集合:rightsideedgeset=。
左側邊集合:leftsideedgeset=。
3,求封口邊。
將divline反向延長得到點veryfarstart,我們假定點veryfarstart足夠遠,以至於divpointlist中的所有點都在射線[veryfarstart,end)上。
然後我們根據到veryfarstart的距離對divpointlist中的點進行排序,得到divpointlist_sorted=(1,2,3,8,7,4,5,6)。
然後把divpointlist_sorted中的點相鄰兩個結對兒,得到12,38,74,56。可以發現規律:
線段12,線段38,線段74,線段56,正好都是左側子多邊形的封口。
而將上面每個線段都反向,得到:線段21,線段83,線段47,線段65,正好都是右側子多邊形的封口。
所以有:
leftsidecapset=,
rightsidecaplist=。
4,重新組裝。
右側邊和封口形成的集合為rightsideedgeandcapset=rightsideedgeset與rightsidecapset的並集=,
左側邊和封口形成的集合為leftsideedgeandcapset=leftsideedgeset與leftsidecapset的並集=。
對rightsideedgeandcapset中的邊進行組裝,可得多邊形:1bc2,3fg47no8,5jk6,
對leftsideedgeandcapset中的邊形行組裝,可得多邊形:a12de38p,4hi56lm7
(注意,組裝過程並不需要比較座標(比較座標的方法不但效率低,而且特殊情況還有可能產生錯誤),只需對線段端點字母進行匹配即可)。
所以凹多邊形abcdefghijklmnop被直線(start,end)切割成五個子多邊形:1bc2,3fg47no8,5jk6,a12de38p,4hi56lm7。
計算完畢。
二,實現
在unity裡進行了試驗,效果如下:
求任意多邊形面積(凹多邊形和凸多邊形)
遇到問題 已知多邊形的各個左邊點,要求多邊形的面積 然後我搜尋了下看到這篇文章 這個人說的不多,但是簡單明瞭 首先已知各定點的座標分別為 x1,y1 x2,y2 x3,y3 xn,yn 則該多邊形的面積公式為 s 1 2 x1 y2 x2 y1 x2 y3 x3 y2 xk yk 1 xk 1 yk...
OpenGL學習 點 直線 多邊形
上一課中,我們學習了如何繪製幾何圖形,但大家如果多寫幾個程式,就會發現其實還是有些鬱悶之處。例如 點太小,難以看清楚 直線也太細,不舒服 或者想畫虛線,但不知道方法只能用許多短直線,甚至用點組合而成。這些問題將在本課中被解決。下面就點 直線 多邊形分別討論。1 關於點 點的大小預設為1個畫素,但也可...
acm 凹多邊形面積 ACM 學習路線
1.學好專業課知識 理解資料庫原理 優化,計算機組成原理,概率論,線性代數,作業系統,c c 高等數學,資料結構,演算法,離散數學,網路協議,socket程式設計 編譯原理,軟體工程,設計模式,linux伺服器搭建。指令碼程式設計。stl原始碼分析,多執行緒程式設計。1.c基礎語法必須全部學完 2....