簡體   English   中英

繪制幾乎直線

[英]Drawing an almost straight line

我得到的這些數組代表方形紙,如果你願意,也可能是像素。 為了在該線程中保持一致,讓“1”表示黑色單元格,“0”表示白色單元格。

現在,我想繪制從A點到B點的(黑色)直線。我不能只使用香草http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ,因為我需要將每個單元格變黑如果它是一張方形紙並且你從方形A的中心到方形B的中心畫一條線就會被擊中。

所以這些應該如下:

+—+—+—+    +—+—+—+
|A| | |    |█| | |
+—+—+—+    +—+—+—+
| | | |    |█|█| |
+—+—+—+    +—+—+—+
| | | | →  | |█|█|
+—+—+—+    +—+—+—+
| | |B|    | | |█|
+—+—+—+    +—+—+—+

+—+—+—+    +—+—+—+
|A| | |    |█| | |
+—+—+—+    +—+—+—+
| | | | →  | |█| |
+—+—+—+    +—+—+—+
| | |B|    | | |█|
+—+—+—+    +—+—+—+

+—+—+—+    +—+—+—+
|A| | | →  |█|█| |
+—+—+—+    +—+—+—+
| | |B|    | |█|█|
+—+—+—+    +—+—+—+

隨意想象這些草圖更像方形,或者在一張方形紙上實際繪制草圖! 它可能會搞清楚。

和往常一樣,隨意發布可能有用的任何內容。 謝謝!


(一個解法

也使用這個例子。 並使用我的框架使用的索引,所以它看起來與答案中的索引略有不同。

 X 0 1 2      X 0 1 2
Y +—+—+—+ →  Y +—+—+—+
0 |A| | | →  0 |█| | |
  +—+—+—+ →    +—+—+—+
1 | | | | →  1 |█|█| |
  +—+—+—+ →    +—+—+—+
2 | | | | →  2 | |█|█|
  +—+—+—+ →    +—+—+—+
3 | | |B| →  3 | | |█|
  +—+—+—+ →    +—+—+—+

A(0,0)= :( a1,a2),B是(2,3)= :( b1,b2),因此預期的點集是{(0,0),(0,1), (1,1),(1,2),(2,2),(2,3)}

首先,我們將在實際紙張上繪制的直線形式化。

Therefore first define constant m which holds our slope:

    (b2 - a2)
m = —————————
    (b1 - a1)

For arbitrary (A, B), the straight is now defined by:
g: y = (x - a1) · m + a2

and inverted:
ǵ: x = (y - a2) / m + a1

Note that for m = 0, the whole thing does fail. But a straight-to-the-right line does not only sound like a straightforward thing.

在這個例子中,直道是

m = 3/2
g: y = x * 3/2
ǵ: x = y * 2/3

我們將在邊界框內使用“線值”(恰好在2個整數x和x + 1之間,廣泛稱為“x和a halve”)來提供這些函數。 首先,我們將介於a1和b1之間(飼料g),然后介於a2和b2之間(飼料ǵ):

g(0.5) = 1/2 * 3/2 = 0.75 // 1 < g(0.5) + 0.5 < 2
g(1.5) = 3/2 * 3/2 = 2.25 // 2 < g(1.5) + 0.5 < 3

ǵ(0.5) = 1/2 * 2/3 = 0.33 // 0 < ǵ(0.5) + 0.5 < 1
ǵ(1.5) = 3/2 * 2/3 = 1    // 1 < ǵ(1.5) + 0.5 < 2
ǵ(2.5) = 5/2 * 2/3 = 1.66 // 2 < ǵ(2.5) + 0.5 < 3
  1. 首先是指直線穿過第一條水平線上方的第一條垂直線(如“下方”所示)。 獲得黑色的點:(0,1),(1,1)。
  2. 第二意味着直線與第二水平線上方的第二垂直線交叉。 變黑的要點:(1,2),(2,2)。
  3. 第三個意味着直線與第0個垂直線之后的​​第一條水平線(顯示為“右邊”)相交。 要點變黑:(0,0),(0,1)。
  4. 第四意味着直線在第一垂直線之后與第二水平線交叉。 變黑的要點:(1,1),(1,2)。
  5. 第五個意味着直線在第二個垂直線之后穿過第三個水平線。 獲得黑色的要點:(2,2),(2,3)。

所有點:{(0,1),(1,1),(1,2),(2,2),(0,0), (0,1)(1,1)(1,2) )(2,2) ,(2,3)}

沒有重復 :{(0,0),(0,1),(1,1),(1,2),(2,2),(2,3)}(這與預期完全一樣)

  • 因此,對於穿過第x個水平線上方的第y垂直線的線,我們繪制(x-1,y)和(x,y)黑色。
  • 對於在第y個垂直線之后穿過第x個水平線的線,我們繪制(x,y-1)和(x,y)。
  • (在這里永遠不會這樣)對於第y個垂直方向橫穿第x個水平右側的線,我們繪制m> 0(x-1,y-1)和(x,y)。 如果m <0,則表示(x-1,y)和(x,y-1)

感覺對,這是我的想法。

有什么想法嗎? 請評論!

~LDer~

讓我們假設我們正在使用這個例子:

+—+—+—+    +—+—+—+
|A| | |    |█| | |
+—+—+—+    +—+—+—+
| | | |    |█|█| |
+—+—+—+    +—+—+—+
| | | | →  | |█|█|
+—+—+—+    +—+—+—+
| | |B|    | | |█|
+—+—+—+    +—+—+—+

這是一個3x4的矩形。

我們需要定義兩個函數:
y(x) = 4 * (1 - x/3)
x(y) = 3 * (1 - y/4)

現在讓我們將矩形內的所有整數xy傳遞給它們。
在每一步我們用坐標繪制黑色像素
[x; ceil(y(x)) - 1] [x; ceil(y(x)) - 1][ceil(x(y)) - 1; y - 1] [ceil(x(y)) - 1; y - 1]

y(0) == 4      # paint 0;3
y(1) == 2.(6)  # paint 1;2
y(2) == 1.(3)  # paint 2;1

x(0) == 3      # paint 2;-1 (-1 is not a valid pixel coordinate, 
               # so we may just throw away this, as there are no pixels below y=0)
x(1) == 2.25   # paint 2;0
x(2) == 1.5    # paint 1;1
x(3) == 0.75   # paint 0;2

x(y)y(x)函數都給出了對角線上一個點的第二個坐標,當我們將整數值傳遞給它們時,我們找到了對角線與網格的交點。
y函數將為我們提供每個垂直線和x函數的所有像素 - 低於每個水平線(這就是y - 1的原因)。 唯一的問題是角落交叉點,它可以通過一個有條件的解決。

初始化給出“正方形”坐標(x,y)的頂點。 對於每個方格, v1是左上角, v2是右上角, v3是右下角, v4是左下角。 計算你的線的方程y = a*x + b

算法

For each square do
    for each vertex of the square do
        calculate valueOfVertex = y - a*x - b
    if two valueOfVertex have an opposite sign
    then cellColor == 1
    else cellcolor == 0

輸出應該是您所期望的。 唯一的問題是,如果一個valueOfVertex = 0而所有其他的都是嚴格正面或負面的。 但它很容易處理。

說明如果線穿過正方形(或像素),則可以找到兩個不在線的同一側的頂點。 因此,一個位於正半平面中,另一個位於負半平面中。

改進一些簡單的技巧將阻止您測試邊界框的每個方塊。 如果你發現一個完全在半平面上的正方形,你可以丟棄一些正方形。 在您的示例中,如果測試的方格在線上方,則可以丟棄上方和右方的所有方格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM