查找由两行定义的区域中的所有整数点

时间:2012-11-19 13:20:26

标签: math graphics

我需要一种有效的方法来获取由两行定义的区域中的所有整数点。

我从由两个点Pt1和Pt2定义的线开始。 然后移动该线,使得得到两个新点Pt1new和Pt2new。 然后我需要找到线条运动产生的区域内的所有欧拉点。

对于简单的情况,它没有问题,因为我将简单地在最小x和y值之间生成矩形区域到最大x和y值。然后检查与欧拉网格建立的交叉点是否实际位于由我的点生成的区域内。 (顺时针方向移动点,检查点是否总是在右侧)

然而对于第二个问题(图像中较低的问题),这似乎不起作用,因为我无法轻易检查该点是否实际位于该区域内。如何以快速简便的方式找到所有这些点。

在图中我有兴趣找到绿点。它位于欧拉网格上(例如x和y坐标是整数值)。

image of problem

2 个答案:

答案 0 :(得分:3)

如果两条线Pt1-Pt2和Pt1new-Pt2new在点P0处相交,则找到三角形Pt1-Pt1new-P0和Pt2-Pt2new-P0中的所有欧拉点。

最简单的方法与您用于四边形的方法相同。计算边界框并测试内部的每个欧拉点。您可能需要使用barycentric coordinates来检查此问题。

作为进一步的概括,您可能希望始终使用三角形:正常的Pt1-Pt2-Pt1new + Pt2-Pt2new-Pt1new和退化的Pt1-Pt1new-P0 + Pt2-Pt2new-P0。

答案 1 :(得分:1)

我认为你需要改变你的参考。

想象一下,你的起源是固定在你的线上的,它实际上是正在移动的网格。你可以清楚地看到,在第一个突出显示的网格点已经向上移动了。在第二个中,网格已旋转,只有突出显示的点已在线上移动。

由于一切都是线性的(这里没有曲线),如果一个点在变换之前的“低于”线,之后低于它,那么它从未越过它。

定义,然后衡量一个点是低于还是高于该线。如果您移动的线的最远端是3个单位,那么我们只需要考虑距离线最多3个单位的网格点。对于这些点中的每一点,测试它是在转换之前和之后的线之下还是之上。如果其状态改变,则该行传递它。如果没有,那就没有。

然后是上面/下面的衡量标准。该行由

定义

y = mx + c

如果

,则点p(px,py)在线上方

py> m.py + c。

在矩阵中,我们可以先将AB线(ax,ay到bx,by)和点(px,py)都转换成A来源:

Q' = Q + | -ax |
         | -ay |

然后我们可以旋转它以使轴与线对齐。由于线与x轴之间的角度由sin(θ)=(dy / d)给出,而cos(θ)=(dx / d):

d = sqrt((by-ay)^2 + (bx-ax)^2)
s = (by-ay)/d
c = (bx-ax)/d

角度的旋转矩阵在this wikipedia page中给出,使用s和c得到:

R = |  c  s |
    | -s  c |

应用平移然后旋转到线条会产生沿x轴的位置,从原点到x = d。然后该点将具有正y值或负y值。所以将此应用于p:

q = R(p+T) = |  c  s | ( |px| + |-ax|  
             | -s  c |   |py|   |-ay|  )

p'x = px - ax
p'y = py - ay
qx =  c * p'x + s * p'y
qy = -s * p'x + c * p'y

假设我们在点P上对两条不同的线AB和CD执行此操作。我们将获得两个点F和G(前后的变换点)。如果出现以下情况,该点已越过界线(

if( signof(fy) != signof(gy) ) {
    // crossed the origin
}

但请注意,这仅测试y。如果线太短而无法到达该点,则该点可能仅仅由该线传递。因此,测试x值是否也发生了变化:

if( (fx < 0) && (gx < 0) ||
    (fx > d) && (gx > d) ) {
    // whooshed past
}

因此,如果你测试这两个,你就会知道这个点是否越过了线而没有过去。

希望明白......