20

如何测试点 P = [xp,yp] 是否在中心 C=[x,y]、a、b 和 phi(旋转角度)给出的某个旋转椭圆的内部/外部?

此时我正在使用以下解决方案:将椭圆和点旋转角度 -phi,然后对点和“未旋转”椭圆的位置进行通用测试。

但是有很多测试点(数千个),我发现这个解决方案很慢。是否有任何直接和更有效的方法来获得旋转椭圆和点的位置?

我不需要代码而是算法。谢谢你的帮助。

4

5 回答 5

43

另一种选择是将所有内容都放入二维旋转椭圆的方程中,看看结果是否小于一个。

因此,如果以下不等式为真,则一个点在椭圆内

椭圆方程

其中 (xp,yp) 是点坐标, (x0, y0) 是椭圆的中心。

我实现了一个小型Mathematica程序,证明这确实有效: 操纵屏幕截图

这是在行动:

动画片

这是代码:

ellipse[x_, y_, a_, b_, \[Alpha]_, x0_: 0, y0_: 0] := 
     (((x - x0)*Cos[\[Alpha]] + (y - y0)*Sin[\[Alpha]])/a)^2
   + (((x - x0)*Sin[\[Alpha]] - (y - y0)*Cos[\[Alpha]])/b)^2;

Manipulate[
 RegionPlot[
  ellipse[x, y, a, b, \[Alpha] \[Degree], Sequence @@ pos] < 1, {x, -5, 5}, {y, -5, 5}, 
  PlotStyle -> If[ellipse[Sequence @@ p, a, b, \[Alpha] \[Degree], Sequence @@ pos] <= 1, Orange, LightBlue], 
  PlotPoints -> 25]
, {{a, 2}, 1, 5, Appearance -> "Labeled"}
, {{b, 4}, 2, 5, Appearance -> "Labeled"}
, {\[Alpha], 0, 180,  Appearance -> "Labeled"}
, {{p, {3, 1}}, Automatic, ControlType -> Locator}
, {{pos, {0, 0}}, Automatic, ControlType -> Locator}]
于 2013-05-29T12:55:01.223 回答
14

您可以简单地将数据输入上述公式。这是我根据 Ajasja 的建议所做的 python 实现:

def pointInEllipse(x,y,xp,yp,d,D,angle):
    #tests if a point[xp,yp] is within
    #boundaries defined by the ellipse
    #of center[x,y], diameter d D, and tilted at angle

    cosa=math.cos(angle)
    sina=math.sin(angle)
    dd=d/2*d/2
    DD=D/2*D/2

    a =math.pow(cosa*(xp-x)+sina*(yp-y),2)
    b =math.pow(sina*(xp-x)-cosa*(yp-y),2)
    ellipse=(a/dd)+(b/DD)

    if ellipse <= 1:
        return True
    else:
        return False
于 2013-05-29T22:10:04.940 回答
9

为了处理椭圆,我更喜欢将它们转换到另一个坐标系,其中椭圆是以原点为中心的单位圆。

如果您将椭圆视为单位圆(半径 1),按 (a,b) 缩放,按 phi 旋转并按 (x,y) 变换,那么生活会变得容易得多。如果你有那个变换矩阵,你可以用它来做一个更简单的包含查询。如果您将点变换到椭圆为单位圆的坐标系中,那么您所要做的就是进行微不足道的单位圆测试。如果“变换”是将单位圆变换为所描述的椭圆的矩阵,则

transformedPoint = transform.Invert().Transform(point);
pointInEllipse = transformedPoint.DistanceTo(0,0) < 1.0;
于 2011-10-30T16:51:04.443 回答
1

下面是算法,我让你开发代码:

  1. 确定椭圆中心和您的点之间的向量 v1
  2. 确定矢量 v1 与世界坐标中 x 轴之间的角度 a1
  3. 从 a1 中减去 phi 得到 a2,我们在局部坐标中的矢量角
  4. 在局部坐标中以角度 a2 确定椭圆上的点 P2,而不是偏移 (x, y)
  5. 计算 L1 和 L2,a1 和 a2 的向量长度

评估:

  1. 如果 L1 < L2 点在里面
  2. 如果 L1 = L2(加/减一个小公差),则该点位于椭圆上
  3. 如果 L2 > L2 点在外面

椭圆参数公式:

x = a*cos(u)
y = b*sin(u)

对 -pi 和 +pi 之间的 u 有效。将 phi 添加到 u 以旋转椭圆。

上面的算法可以通过椭圆方程进行简化和优化。

祝你好运!

于 2011-10-30T16:59:58.890 回答
0

Matplotlib 在 patch 类中有一个 Ellipse 方法,它允许您询问一个点是在补丁内部还是外部。检查此处并查找方法 contains_point()。您将需要使用 Ellipse 类创建椭圆,然后就好像里面有一个点。顺便说一句,matplotlib 是 python 的一个包。

于 2014-10-24T13:17:36.303 回答