[練功房] Point of Impact 尋找彈著點


問題:「平面上有n 條線段、m 個點,有些點在線上,有些點不在線上,該如何正確而有效的區分線上的點呢?」
[Tested in Rhino 4.0 SR 9 + Grasshopper 0.9.0006]

如果當作打靶的話,線是靶,點是子彈,像是在算命中率。打中靶的子彈,無論同時打中幾個靶,都算擊中。

基本觀念是「擊中 = 點在線上 = 點與線的距離為零」。所以直觀做法是每個點分別和每條線計算距離 d,若 d = 0 則表示點在線上。實際應用上我們會容許誤差,也就是趨近於零 d ≈ 0 也可以當做點在線上。直觀解法如下圖:


A: 產生點與線的交叉配對。
B: 求得點與線的距離。輸出參數P為線上的投影點,D為距離值。
C: 距離若小於或等於 0,表示點在線上。輸出一連串布林值。
D: 依布林值過濾投影點。

看似正確,但這個解法會有重複計算投影點的問題!例如下圖中,原本應該只有 6 個點在線上,答案卻得到 7。因為黃色圈圈內的點正好位於兩條線的交點,而兩條線上的投影點會被重複計算。


修改過後的版本如下,每個點所產生的投影點群合併計算,只要大於 1 就算在線上。


A: 輸入參數 A 的點串列用 Graft 前置處理,轉成多重串列,意味著一個點配多條線。
D: 累加(Mass Addition)判斷結果。輸入參數 I 接受各種數值,在此布林值會以 0 和 1 計算。輸出值 R 為累加結果。
E: 過濾點群。輸入參數 P 應該是布林值,但如果輸入是數值,則大於零為 True,等於零為 False。

因為用了 Graft 處理點串列,交叉配對其實就派不上用場了,程式可以改為:


各位可以自己試試以下問題:
1. 被點擊中的線有哪幾條?
2. 同時擊中一條線以上的點有哪幾個?

留言