跳到主要內容

發表文章

目前顯示的是 5月, 2025的文章

三角網格壓縮

三角形是平面上最簡單的多邊形。三角形有許多「好性質」,例如,任何三角形在空間中,三個頂點一定共平面;三角形一定是凸多邊形(多邊形上任取兩個點的連線,若線上的所有點都在此多邊形內,稱為凸多邊形);任何兩個頂點的連線一定不會交叉,等等。因此三角形常做為電腦繪圖的基本元件。 多個三角形可以組成三角網格: 有一種三角網格的變換,把兩個相鄰的頂點合併,如下圖左,$v_1$ 合併至 $v_2$,變成下圖右,$\overline{v_1 v_2}$ 兩邊的兩個三角形消失: 一個方形三角網格可以透過一連串的頂點合併,在整體外型不變的前提下,化簡成兩個三角形: 合併的順序端視規則,例如,應用在地形模塑,每個網格的頂點都對應一個高度資訊,頂點合併的順序可以是,頂點合併後,三角形上的高度誤差最小的頂點先合併。頂點合併前後的誤差,舉例如下圖: 將合併的結果反過來看,原始的三角網格變成一個簡化的三角網格,加上一連串頂點合併的反運算,即頂點分裂: $$ M = M_0 + vsplit(v_{i_1}, v_{i_2}) + vsplit(v_{i_2}, v_{i_3}) + \cdots $$ 如此,$M_0 + \sum_{k=1}^n vsplit_k$ 可視為 $M$ 的一種壓縮格式,隨著 $M_0$ 加上越多的 $vsplit_k$ 而越接近 $M$ 。 並非所有任意的頂點合併都是合法的。例如,一般希望頂點合併後,三角形不會發生重疊。下圖是一個頂點合併後發生三角形重疊的例子: 如何知道是否發生三角形重疊?一種方法是把三角形放在一個三維空間,計算三角形的法向量(normal vector)在頂點合併後是否改變方向: 法向量 $\vec{n}$ 的計算,可透過外積: $$ \vec{n} = \overrightarrow{v_av_b} \times \overrightarrow{v_av_c} $$ 若三角形放在 $x-y$ 平面 ($z=0$),則 $\vec{n}$ 可表示為一個數字 $$ \vec{n} = [0, 0, n] \\ n = (v_{b_x} - v_{a_x})(v_{c_y} - v_{a_y}) - (v_{b_y} - v_{a_y})(v_{c_x} - v_{a_x}) $$ 另一種...

羊狼過河

問題: 人、狼、羊、白菜要從河的此岸藉由一艘船渡河至另一岸,其中只有人會划船,每次人只能帶一件東西搭船渡河, 且狼和羊、羊和白菜不能在無人監視的情況下放在一起。 在這些條件下,在最小渡河次數下,如何才能讓大家都渡河至另一河岸? 分析: 一般常用圖論(graph theory)的方式求解。我們用暴力法試試,利用電腦程式搜尋可能的解答。 (使用 python) 先給各個角色一個代號: c_cabbage = 1 c_sheep = 2 c_wolf = 3 因為人負責划船,而划船是搬運的唯一方法,人必定是最後到對岸的,因此不需代號。 使用兩個 list 表示兩岸的到貨狀態,例如 $$ [1,2,3],[] $$ 表示白菜、羊、狼在起始岸,目的岸空無一物。 使用一連串的 list 即可表示搬運的過程,例如: $$ [[1,2,3],[]], \\ [[1,3],[2]] $$ 表示人划船把羊載到目的岸。 以下函式檢查合法性,也就是某一岸邊的狀況是否安全,沒有發生吃貨的情況: def constraint_check(grp): return not ((c_cabbage in grp and c_sheep in grp) or (c_sheep in grp and c_wolf in grp)) 以下函示列舉可能的搬運過程,交錯反覆地從起始岸載一個物體到目的岸,或從目的岸載一個物體到起始岸。從目的岸返回時也可空手。為了防止無限循環,要排除重複的搬運,以及,除非發生吃貨風險,不從目的岸載運物體回起始岸。 def new_move(curr, pt): for i in curr: if (pt == i): return False return True def part_enum(st): if (len(st) == 0): return [] que = [[ st.copy() ]] ans = [] while(que): head = que.pop(0) if (head[-1][0] =...

最後的輸

一個簡單的遊戲:數個方格,不一定組成方形,由兩人依序在格子內劃 X,可沿水平或垂直劃一格或多格,但每個格子只能劃一次。劃最後一格的人輸。 例:以下的方格組,並限制一次最多劃連續 3 格 A、B 兩人輪流劃 x 。 A 先劃 X X B 劃 X X X X A 劃,剩一格,B 輸了: X X X X X X 問題:對於一個方格組以及劃格上限,是否有必勝的策略? 先看一個簡單的類型,如果每次只能劃一格,且方格的總數是偶數,先劃的人一定贏! 如果方格組的形狀不規則,或是每次可以劃多格,似乎就沒有簡單的答案了? 使用程式來列舉所有的戰局看看: (使用 python) 首先把每一格對應一個數字 $1,2,...$,並定義"連接性",也就是某一格可以連到其他哪些格。為了避免重複列舉,只看右方與下方的格子。 例如,對於以下的九宮格 1 2 3 4 5 6 7 8 9 劃格上限 3,定義連接關係 dir_mov = {1: [[2,3], [4,7]], 2: [[3],[5,8]], 3: [[6,9]], 4: [[5,6],[7]], 5: [[6],[8]], 6: [[9]], 7: [[8,9]], 8: [[9]], } 使用遞迴的方式,將方格組分割: $$ \text{partition}(S) = \bigcup_{b\subseteq S}\text{先劃 } b \text{,然後 partition}(S-b) $$ # max consecutive items M = 3 # output: arr...