[英]Drawing an almost straight line
I got these arrays representing squared paper, or maybe pixels if you like. 我得到的这些数组代表方形纸,如果你愿意,也可能是像素。 For consistency in this thread, let "1" represent a black cell, "0" represent a white cell. 为了在该线程中保持一致,让“1”表示黑色单元格,“0”表示白色单元格。
Now, I want to draw a (black) straight line from point A to point B. I can't just use a vanilla http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm , because I need to blacken every cell that would be hit if it were a sheet of squared paper and you drew a line from the center of square A to the center of square B. 现在,我想绘制从A点到B点的(黑色)直线。我不能只使用香草http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ,因为我需要将每个单元格变黑如果它是一张方形纸并且你从方形A的中心到方形B的中心画一条线就会被击中。
So these should work out as follows: 所以这些应该如下:
+—+—+—+ +—+—+—+
|A| | | |█| | |
+—+—+—+ +—+—+—+
| | | | |█|█| |
+—+—+—+ +—+—+—+
| | | | → | |█|█|
+—+—+—+ +—+—+—+
| | |B| | | |█|
+—+—+—+ +—+—+—+
+—+—+—+ +—+—+—+
|A| | | |█| | |
+—+—+—+ +—+—+—+
| | | | → | |█| |
+—+—+—+ +—+—+—+
| | |B| | | |█|
+—+—+—+ +—+—+—+
+—+—+—+ +—+—+—+
|A| | | → |█|█| |
+—+—+—+ +—+—+—+
| | |B| | |█|█|
+—+—+—+ +—+—+—+
Feel free to imagine these sketches to be more square-like, or to actually sketch that on a sheet of squared paper! 随意想象这些草图更像方形,或者在一张方形纸上实际绘制草图! It might clear things up. 它可能会搞清楚。
And like always, feel free to post anything that might help. 和往常一样,随意发布可能有用的任何内容。 Thanks! 谢谢!
(A) Solution (一个解法
Also using this example. 也使用这个例子。 And using the indices as they're used by my framework, so it looks a little different than the one in the answers. 并使用我的框架使用的索引,所以它看起来与答案中的索引略有不同。
X 0 1 2 X 0 1 2
Y +—+—+—+ → Y +—+—+—+
0 |A| | | → 0 |█| | |
+—+—+—+ → +—+—+—+
1 | | | | → 1 |█|█| |
+—+—+—+ → +—+—+—+
2 | | | | → 2 | |█|█|
+—+—+—+ → +—+—+—+
3 | | |B| → 3 | | |█|
+—+—+—+ → +—+—+—+
A being (0,0) =: (a1,a2), B being (2,3) =: (b1,b2), so the expected set of points is {(0,0), (0,1), (1,1), (1,2), (2,2), (2,3)} A(0,0)= :( a1,a2),B是(2,3)= :( b1,b2),因此预期的点集是{(0,0),(0,1), (1,1),(1,2),(2,2),(2,3)}
First, we formalize the straight which would be drawn on actual paper. 首先,我们将在实际纸张上绘制的直线形式化。
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.
in this example, the straights are 在这个例子中,直道是
m = 3/2
g: y = x * 3/2
ǵ: x = y * 2/3
We'll feed these functions with the "line values" (exactly between 2 integers x and x+1, widely known as "x and a halve") within our bounding box. 我们将在边界框内使用“线值”(恰好在2个整数x和x + 1之间,广泛称为“x和a halve”)来提供这些函数。 So first we'll go between a1 and b1 (feed g), then between a2 and b2 (feed ǵ): 首先,我们将介于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
All points: {(0,1), (1,1), (1,2), (2,2), (0,0), (0,1) , (1,1) , (1,2) , (2,2) , (2,3)} 所有点:{(0,1),(1,1),(1,2),(2,2),(0,0), (0,1) , (1,1) , (1,2) ) , (2,2) ,(2,3)}
Without duplicates : {(0,0), (0,1), (1,1), (1,2), (2,2), (2,3)} (which is exactly as expected) 没有重复 :{(0,0),(0,1),(1,1),(1,2),(2,2),(2,3)}(这与预期完全一样)
Feels about right, that's my idea. 感觉对,这是我的想法。
Any thoughts? 有什么想法吗? Please comment! 请评论!
~ LDer ~ ~LDer~
Let's assume that we're working with this example: 让我们假设我们正在使用这个例子:
+—+—+—+ +—+—+—+
|A| | | |█| | |
+—+—+—+ +—+—+—+
| | | | |█|█| |
+—+—+—+ +—+—+—+
| | | | → | |█|█|
+—+—+—+ +—+—+—+
| | |B| | | |█|
+—+—+—+ +—+—+—+
It's a rectangle 3x4
. 这是一个3x4
的矩形。
We need to define two functions: 我们需要定义两个函数:
y(x) = 4 * (1 - x/3)
x(y) = 3 * (1 - y/4)
. x(y) = 3 * (1 - y/4)
。
Now let's pass to them all integer x
and y
inside our rectangle. 现在让我们将矩形内的所有整数x
和y
传递给它们。
On each step we are painting black pixel with coordinates 在每一步我们用坐标绘制黑色像素
[x; ceil(y(x)) - 1]
[x; ceil(y(x)) - 1]
and [ceil(x(y)) - 1; y - 1]
[x; ceil(y(x)) - 1]
和[ceil(x(y)) - 1; y - 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
Both x(y)
and y(x)
functions are giving you second coordinate of a point on the diagonal, and when we're passing integer values to them, we're finding intersections of our diagonal with the grid. x(y)
和y(x)
函数都给出了对角线上一个点的第二个坐标,当我们将整数值传递给它们时,我们找到了对角线与网格的交点。
The y
-function would give us all pixels that are right to every vertical line and the x
-function - that are below every horizontal (that's why y - 1
). y
函数将为我们提供每个垂直线和x
函数的所有像素 - 低于每个水平线(这就是y - 1
的原因)。 The only issue will be with corner intersections, it can be solved by one more conditional. 唯一的问题是角落交叉点,它可以通过一个有条件的解决。
Initialisation Give the vertices of your "squares" coordinates (x,y)
. 初始化给出“正方形”坐标(x,y)
的顶点。 For each square, v1 is top left, v2 top right, v3 bottom right and v4 bottom left. 对于每个方格, v1是左上角, v2是右上角, v3是右下角, v4是左下角。 Calculate the equation of your line y = a*x + b
. 计算你的线的方程y = a*x + b
。
Algorithm 算法
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
The output should be what you expect. 输出应该是您所期望的。 The only problem maybe if one valueOfVertex = 0
and all the others are stricly positive or negative. 唯一的问题是,如果一个valueOfVertex = 0
而所有其他的都是严格正面或负面的。 But it's easy to handle. 但它很容易处理。
Explanation If the line crosses the square (or pixel), you can find two vertice which aren't on the same side of the line. 说明如果线穿过正方形(或像素),则可以找到两个不在线的同一侧的顶点。 So one lies in the positive half plane, the other in the negative half plane. 因此,一个位于正半平面中,另一个位于负半平面中。
Improvement Some simple tricks will prevent you from testing every square of the bounding box. 改进一些简单的技巧将阻止您测试边界框的每个方块。 If you find a square that is entirely in a half plane, you can discard some squares. 如果你发现一个完全在半平面上的正方形,你可以丢弃一些正方形。 In your examples, if the square tested is above the line, you can discard all the squares that are above and to the right. 在您的示例中,如果测试的方格在线上方,则可以丢弃上方和右方的所有方格。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.