计算给定侧的法线

Calculating normal to line towards given side

给定的是一条线(线段),由两个向量 start(x,y)end(x,y) 定义。我还有一个点 p(x,y),它位于由线分隔的两个区域中的任何一个(即 而不是 正好在线上)。

如何计算朝向 p 所在一侧的线的法线?

我的数学能力有点生疏,所以我不能给你准确的计算,但你做的是这样的(假设你的描述是二维的):

  1. 首先你计算一个正常的n。
  2. 然后计算 P',它是点 P 到直线的垂直投影。 基本上,你要做的是,你 "create" 另一条线,并使用步骤 1 中的向量 n 作为方向(y = p + x * n 其中 y、p 和 n 是向量,p 实际上是你的 p(x,y ) 和 x 是一个实数), 然后你把这条线和第一条线相交, 它们相交的点是 P'.
    看到你是奥地利人,请大家原谅我用了一个德语单词,我真的不知道英文翻译,也找不到。 P' = Lotfußpunkt
  3. 计算 P - P'。如果它在两个分量中都具有与 n 相同的符号,则 n 就是您要搜索的法线。如果它有相反的符号,-n 就是您要搜索的那个。

虽然我不知道所有的英文技术术语,但我希望思路清晰。

为了 开始 = (a,b) 结束 = (c,d) p = (x,y)

坡度(起点终点)= (d - b) / (c - a)

斜率(范数) = -(c - a) / (d - b)

范数线必须包含 p = (x,y),所以

ynorm = -((c - a) / (d - b)) * xnorm + (y + ((c - a) / (d - b)) * x)

设:

A = (a,b) and B = (c,d) define the line segment
P = (p,q) be the other point.

定义:

dot( (p,q), (r,s) ) == p*r + q*s

然后向量:

v = ( c-a, d-b)

定义沿线段的方向。它的垂线是:

u = (d-b, (-(c-a)) = (d-b,a-c)

这个可以用v做点积看出来。要从垂线得到法线,只需除以它的长度:

n = u /|u|, |u| = sqrt( dot(u,u))

我们现在只需要知道 P 相对于法线的位置。如果我们采取:

dir = dot( (P-A), n) ) 

dir > 0表示nP方向相同,而dir < 0表示方向相反。应该dir == 0,那么P其实是在延长线上(不一定是线段本身)。

首先,通过取 end-startp-end 的叉积:

来确定点位于直线的哪一侧

z = (xend-xstart)(yp-yend) - (yend-ystart)(xp-xend)

如果 z>0,则该点位于线的左侧(如站在 start 并面向 end[=65 的人所见=]).如果 z<0,则该点位于线的右侧。

二、归一化线段:

S = 结束 - 开始
k = S/|S|

最后,如果点在直线的左边,则向左旋转k

(xk, yk) => (-yk, x k)

或者如果点在直线的右侧,则向右旋转k

(xk, yk) => (yk, -x k)

y = mx + c

是法线方程,其中 m 是斜率,c 是任意常数。

你有开始和结束。让我们称它们为 (x1,y1) 和 (x2,y2) 以及连接它们的线 L1。 这条线的斜率 m1 是 (y2-y1)/(x2-x1)。这条线垂直于您需要的线,我们可以将其称为斜率为 m2 的 L2。 2条互垂线的斜率乘积为-1。因此, m1*m2=-1。

因此你可以计算m2。现在,您需要找到直线 L2 的方程。直线 P (x,y) 中有 1 个点。您可以用这种方式替换: y=m2*x+c。

这会给你c。有了线方程后,您可以将其转换为参数形式,如下所示:

http://thejuniverse.org/PUBLIC/LinearAlgebra/LOLA/lines/index.html

直线方程给出为

A = start.y-end.y
B = end.x-start.x
C = start.x*end.y-start.y*end.x

A*x + B*y + C = 0

p=(px,py)到直线的最小距离d

d = (A*px+B*py+C)/sqrt(A^2+B^2)

如果值为正,则该点位于矢量 (start->end) 的逆时针方向。如果为负则顺时针旋转。因此,如果 (start->end) 指向上方,则线的左侧为正距离。

例子

start = (8.04, -0.18)
end = (6.58, 1.72)
P = (2.82, 0.66)
A = (-0.18)-(1.72) = -1.9
B = (6.58)-(8.04) = -1.46
C = (8.04)*(1.72)-(-0.18)*(6.58) = 15.01
d = (A*(2.82)+B*(0.66)+C)/√(A^2+B^2) = 3.63

d 的计算显示与草图中向量 (near->P) 的长度相同的值。

N = (Ey - Sy, Sx - Ex)垂直于直线(SE旋转90°,未归一化)。

然后计算点积的符号

N . SP = (Ey - Sy)(Px - Sx) + (Sx - Ex)(Py - Sy),

它会告诉你法线指向哪一侧。