優雅高效的多邊形對稱性判定算法

前言

在計算幾何、機器人運動規劃、圖像輪廓分析中,我們常常需要知道一個平面圖形的對稱性(包括旋轉對稱、軸對稱和鏡像對稱)。那麼給定一個平面簡單多邊形,是否存在O(n)的算法,找出其所有的對稱軸和旋轉對稱角度?

答案是肯定的。下面我們一起來看看這一優雅高效的算法吧。

對稱問題的巧妙轉化

對於對稱性求解,一個直接的方法就是逐個頂點依次嘗試(對於軸對稱,還要嘗試邊的中點),然後判斷圖形是否重合,但是這種做法時間複雜度O(n^2),太過愚蠢。

其實上述逐點嘗試比對的過程,有點像字符串匹配問題:在字符串A中尋找字符串S。

假設串B的長度爲n,串A的長度爲m,我們知道KMP算法可以在O(m+n)的時間複雜度內找到A中所有S的匹配位置。

我們將KMP算法推廣一下,它可以用於任何信息串的匹配。只要修改相應的比較函數即可。

將多邊形按照某種規則進行編碼,得到模式串S,然後通過合理構造匹配串A,使用KMP算法在A中尋找S的匹配,即可求解得到S的對稱性。利用KMP思想判斷對稱性的過程如下:

  1. 編碼:將多邊形按照某種規則進行編碼,編碼成信息串S;
  2. 構造匹配串:根據要判斷旋轉對稱還是軸對稱來構造不同的匹配信息串A
  3. 匹配:用KMP算法在A中尋找S的匹配位置
  4. 解碼:找到對稱軸/對稱角度

下面對此進行詳細說明。

旋轉對稱

                                     

旋轉對稱就是要求解一個圖形的旋轉對稱角度:上圖中,左圖的對稱角度是360/3=120度,右圖是360/5=72度。

我們需要先將多邊形的每一個頂點信息編碼爲二元組(Length, Angle),其中Length爲邊長、Angle爲頂點的內角。

上圖中,邊長均爲l,那麼多邊形編碼爲如下數組:

                     [(l, \beta),(l, \alpha),(l, \beta),(l, \alpha), (l, \beta), (l, \alpha), (l, \beta),(l, \alpha)]

對於任意一個多邊形,假設其編碼爲:S=[s_o,s_1,...,s_{n-1}]

那麼構造旋轉對稱的匹配串如下:A=[s_1,...,s_{n-1},s_o,s_1,...,s_{n-1}]

讀者可以思考一下:爲什麼這麼構造呢?這麼構造,以下三點是成立的:

  • 匹配位置對應旋轉角度
  • 收割匹配位置不爲s_0,則是旋轉對稱圖形
  • 旋轉角度爲:首個匹配位置(從1開始)*360/n,n是S的長度

構造出了模式串和匹配串,利用KMP算法尋找匹配即可得到旋轉對稱角度。

 

軸對稱

       

軸對稱判定需要找出所有的對稱軸。上圖中雪花有6條對稱軸,而蝴蝶只有1條對稱軸。

對於軸對稱,每個頂點處的編碼二元組與旋轉對稱一樣。但是整個多邊形的編碼序列則有所不同,如下:

                                                                        S=[s_{n-1},s_{n-2},...,s_0]

原因如下圖:

軸對稱後邊長和夾角的順序改變,所以要將編碼序列倒序,且其中的S_{n-1}{P_{n-1}P_0的長度; P_1-P_0-P_{n-1}的夾角}。

匹配串A的編碼序列基本不變:A=[s_0,s_1,...,s_{n-1},s_o,s_1,...,s_{n-1}].

對於軸對稱,其解碼規則如下:

  • 每個匹配位置對應一個對稱軸
  • 對稱軸的另一個端點在對面
  • 匹配位置每往後一個,對稱軸經過的頂點後移半個(頂點移動半個是中點)

以下圖爲例,匹配位置爲(012345):

 

紅色數字表示頂點的編碼順序,而綠色數字表示解碼出的對稱軸。
 
算法原理清楚了,相信讀者不難寫出代碼,這裏不再贅述。如有需要可以私信本人。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章