我需要计算点与椭圆之间的距离。在我的程序中,我将椭圆描述为坐标x = acosφ和y = bsinφ(其中a、b是常数,φ是变化的角度)。
我想计算点P与我的椭圆之间的最短距离。我的想法是计算从椭圆中心到点P的向量,然后找到从中心开始并朝向点P并在椭圆末端到达的向量,并在末端减去两个向量以得到距离(这可能不会给出最短距离,但对于我所需的情况仍然可以)。问题是我不知道如何计算第二个向量。有人有更好的想法或可以告诉我如何找到第二个向量吗?
提前谢谢!
编辑2:我还展示了椭圆的另一半给出了这个结果: 所以我们可以看到,这只有在
我们可以看到这里发生了什么: 这很奇怪,所有点都停留在那个“象限”里。但我还注意到,当我将绿框远离椭圆时,它似乎会得到正确的距离向量。
可能是什么原因呢?
我想计算点P与我的椭圆之间的最短距离。我的想法是计算从椭圆中心到点P的向量,然后找到从中心开始并朝向点P并在椭圆末端到达的向量,并在末端减去两个向量以得到距离(这可能不会给出最短距离,但对于我所需的情况仍然可以)。问题是我不知道如何计算第二个向量。有人有更好的想法或可以告诉我如何找到第二个向量吗?
提前谢谢!
编辑1:
问题:计算的角度似乎不能给出正确的椭圆上的点
根据的建议,我得到了这个结果:
白色部分是由计算距离的程序创建的。我使用从椭圆中心P到身体中心的向量计算角度phi。但是,由于我在椭圆的方程中使用角度来获取应该停留在椭圆上且具有与第一个计算向量相同方向的点(如果我们将该点视为向量),因此实际上会得到上面显示的“延迟”向量。可能出了什么问题?我真的无法理解这种行为(是否与atan2有关)。编辑2:我还展示了椭圆的另一半给出了这个结果: 所以我们可以看到,这只有在
phi = -+pi/2
和phi = -+pi
的情况下才有效。
实现失败
我尝试使用 MARTIN R 的实现,但我仍然做错了事情。
起初我以为可能是中心点(不总是相同的)的问题,于是我这样改变了实现方式:
func pointOnEllipse(ellipse: Ellipse, p: CGPoint) -> CGPoint {
let maxIterations = 10
let eps = CGFloat(0.1/max(ellipse.a, ellipse.b))
// Intersection of straight line from origin to p with ellipse
// as the first approximation:
var phi = atan2(ellipse.a*p.y, ellipse.b*p.x)
// Newton iteration to find solution of
// f(θ) := (a^2 − b^2) cos(phi) sin(phi) − x a sin(phi) + y b cos(phi) = 0:
for _ in 0..<maxIterations {
// function value and derivative at phi:
let (c, s) = (cos(phi), sin(phi))
let f = (ellipse.a*ellipse.a - ellipse.b*ellipse.b)*c*s - p.x*ellipse.a*s + p.y*ellipse.b*c - ellipse.center.x*ellipse.a*s + ellipse.center.y*ellipse.b*c
//for the second derivative
let f1 = (ellipse.a*ellipse.a - ellipse.b*ellipse.b)*(c*c - s*s) - p.x*ellipse.a*c - p.y*ellipse.b*s - ellipse.center.x*ellipse.a*c - ellipse.center.y*ellipse.b*s
let delta = f/f1
phi = phi - delta
if abs(delta) < eps { break }
}
return CGPoint(x: (ellipse.a * cos(phi)) + ellipse.center.x, y: (ellipse.b * sin(phi)) + ellipse.center.y)
}
我们可以看到这里发生了什么: 这很奇怪,所有点都停留在那个“象限”里。但我还注意到,当我将绿框远离椭圆时,它似乎会得到正确的距离向量。
可能是什么原因呢?
最终结果
使用更新版本的 MARTIN R(进行了3次迭代)