Ada*_*Lee 8 algorithm math geometry computational-geometry
在2D平面中,我有一个点和一条线.如何沿着这条线获得镜像点?
AnT*_*AnT 18
当这样的事情在计算机程序中完成时,您可能必须处理的问题之一是仅使用整数运算(或尽可能多)执行这些计算,假设输入是整数.尽可能以整数形式执行此操作是一个单独的问题,我在此不会介绍.
以下是"数学"解决方案,如果按字面实现将需要浮点计算.我不知道你的情况是否可以接受.您可以自己根据自己的喜好进行优化.
(1)代表的线L通过
A * x + B * y + C = 0
Run Code Online (Sandbox Code Playgroud)
方程.请注意,vector (A, B)是此行的法线向量.
例如,如果线通过两个点来定义X1(x1, y1)和X2(x2, y2),然后
A = y2 - y1
B = -(x2 - x1)
C = -A * x1 - B * y1
Run Code Online (Sandbox Code Playgroud)
(2)通过将所有系数除以向量的长度来归一化方程(A, B).即计算长度
M = sqrt(A * A + B * B)
Run Code Online (Sandbox Code Playgroud)
然后计算值
A' = A / M
B' = B / M
C' = C / M
Run Code Online (Sandbox Code Playgroud)
等式
A' * x + B' * y + C' = 0
Run Code Online (Sandbox Code Playgroud)
仍然是你的线的等价方程,L除了现在法线向量(A', B')是单位向量.
(3)拿你的观点P(px, py)来计算价值
D = A' * px + B' * py + C'
Run Code Online (Sandbox Code Playgroud)
这将为您提供从您的点到您的线的签名距离.换句话说,这是距离最近点的距离(我们并不真正关心最近点本身,我们只需要距离).DPLPL
牌子上写着其侧线的L点P位于.如果P位于同一侧,则向量(A', B')指向("正"侧),距离为正.如果P位于另一侧("负"侧),则距离为负.
(4)为了找到你的镜像点,P'(px', py')你需要将你的点移动到线P的绝对距离到另一边.|2 * D|L
"跨越线"真的意味着如果点P位于"正"侧L,那么我们必须将它向矢量方向移动(A', B')到"负"侧.反之亦然,如果点P位于"负"侧L,那么我们必须将它向矢量方向移动(A', B')到"正"侧.
这可以简单地表示为将点移动到-2 * D向量方向上(注意减去)(A', B').
这意味着
px' = px - 2 * A' * D
py' = py - 2 * B' * D
Run Code Online (Sandbox Code Playgroud)
给你镜像点P'(px', py').
另外,您也可以使用基于寻找实际的最近点的方法N就行L,然后体现自己的点P与关系N.这已在其他答案中提出,我将描述我是如何做到的.
(1)建立一个等式
A*x + B*y + C = 0
Run Code Online (Sandbox Code Playgroud)
为您的线路L在上述步骤1中精确描述.没有必要对这个等式进行标准化.
(2)建立通过的垂直线的方程P.假设垂直线表示为
D*x + E*y + F = 0
Run Code Online (Sandbox Code Playgroud)
在D和E系数马上知道
D = B
E = -A
Run Code Online (Sandbox Code Playgroud)
而F可以通过将点代P入等式来计算
F = -D*px - E*py
Run Code Online (Sandbox Code Playgroud)
(3)通过求解两个线性方程组来求出这两条线的交点
A*x + B*y = -C
D*x + E*y = -F
Run Code Online (Sandbox Code Playgroud)
在这种情况下,克莱默的规则非常有效.维基百科中的Line intersection文章中给出的公式只不过是将Cramer规则应用于此系统.
该解决方案为您提供了N(nx, ny)我们寻找的最近点.
(4)现在算一算
px' = nx + (nx - px)
py' = ny + (ny - py)
Run Code Online (Sandbox Code Playgroud)
找到你的观点P'(px', py').
请注意,此方法几乎可以完全以整数实现.可能失去精确度的唯一步骤是在步骤3中克莱默规则内部的划分.当然,像往常一样,你必须为"几乎整体"解决方案付出的代价是需要大量算术.甚至系数C也F可以溢出,甚至没有提到Cramer规则公式中的计算.
细节取决于您的线的表示方式.如果你将它表示为线上的任意点P以及沿线的单位列向量n,则镜像点Q '到任意点Q由下式给出:
Q '= Q + 2(I - nn T)(P - Q)
(在此,I是2×2单位矩阵,Ñ Ť是的转置Ñ(治疗Ñ为2×1矩阵),以及NN Ť是通过标准矩阵乘法形成的2×2矩阵Ñ与Ñ Ť.)这不是太硬表明如果你将P移动到任何地方,Q '将不会改变.
将其他线表示转换为点/单位矢量表示并不困难.
假设线的方程是ax + by + c = 0.现在想象一条垂直于它的线,它可以表示为-bx + ay + d = 0(两条垂直线的斜率的乘积为-1).现在的问题是找到d.将点的坐标放在第二行,您将d轻松获得值.
第二部分是,在第二行找到一个与第一行等距离等距的点.为此,您可以找到两条线的交点.计算的差异x和y给定的点和交会点的.现在将它们添加到交叉点的x和y值.这给出了你需要的点(你可能需要否定差异 - 这取决于你使用的减法顺序).