【问题标题】:Collision with Ellipse与椭圆碰撞
【发布时间】:2012-01-15 03:13:27
【问题描述】:

对于一个椭圆台球台,如何检测和解决台球台边界和一个台球之间的碰撞?

1.) 我想看看台球的位置 P(x,y) 是否位于

  • 里面
  • 开启
  • 在椭圆的边界之外[更新:第 1 部分已解决]

2.) 如果它位于边界,则必须计算新速度(仅翻转速度是不够的)。

3.) 如果它位于外部,则必须向后移动才能首先位于边界上。

            ========
        ====      * ====
    ====                ====
    =                      =
    ====                ====
        ====        ====
            ========

给定的是台球的位置P(x,y)和速度V(x,y),加上椭圆中心的位置C(x_0,y_0)和两个半轴a,b的椭圆。

【问题讨论】:

  • 尽管我喜欢解决此类问题,但您打算编写解决方案代码吗?
  • 另外,你是否只想看看 P(x,y) 是否在椭圆的边界上?
  • 我编辑了我的问题以包含更多细节。我已经画了一个圆圈,但我似乎找不到椭圆的正确起点。

标签: geometry collision ellipse


【解决方案1】:

由于您正在考虑椭圆(因此是凸面)板,我想您可以使用基于GJK 的东西。您将获得碰撞期间的接触点和表面法线,以及在没有碰撞时对象与相关见证点之间的最小距离。

使用 GJK 进行碰撞检测非常快,您可以非常轻松地为其他形状实现它(您只需要重新编码 support function)。对于椭圆,我认为支持函数是这样的(尝试验证):

h=((x^2)/(a^4)+(y^2)/(b^4))^(-1/2)

一些链接:

【讨论】:

  • 谢谢,但我想找到自己的解决方案(需要一些帮助)。
【解决方案2】:

只需像使用圆方程一样使用椭圆方程:

((p.x-x0)/a)^2 + ((p.y-y0)/b)^2 = k

如果 k 在椭圆内

如果 k == 1 -> 在椭圆上

如果 k > 1 -> 在椭圆之外

【讨论】:

  • 不知道为什么我没看到,谢谢!现在不太愉快的部分:如果球在椭圆之外,则需要将其设置回椭圆边界上​​的相应点(即球设法在两帧之间逃脱)。此外,我刚刚注意到仅仅翻转速度是不够的。相反,我需要计算新的速度?
  • 您的意思是“如果 k==1 -> 在椭圆上”吗?
【解决方案3】:

一些有趣的椭圆表实验。 Delphi 代码(没有错误处理!)。

//calculates next ball position in ellipse
//ellipse semiaxes A, B, A2 = A * A, B2 = B * B
//center CX, CY
//PX,PY - old position, VX,VY - velocity components
//V - scalar velocity V = Sqrt(VX * Vx + VY * VY)

procedure TForm1.Calc;
var
  t: Double;
  eqA, eqB, eqC, DD: Double;
  EX, EY, DX, DY, FX, FY: Double;
begin
  //new position
  NPX := PX + VX;
  NPY := PY + VY;

  //if new position is outside
  if (B2 * Sqr(NPX) + A2 * Sqr(NPY) >= A2 * B2) then begin

    //find intersection point of the ray in parametric form and ellipse
    eqA := B2 * VX * VX + A2 * VY * VY;
    eqB := 2 * (B2 * PX * VX + A2 * PY * VY);
    eqC := -A2 * B2 + B2 * PX * PX + A2 * PY * PY;
    DD := eqB * eqB - 4 * eqA * eqC;
    DD := Sqrt(DD);

    //we need only one bigger root
    t := 0.5 * (DD - eqB) / eqA;

    //intersection point
    EX := PX + t * VX;
    EY := PY + t * VY;

  //mark intersection position by little circle
    Canvas.Ellipse(Round(EX - 2 + CX), Round(EY - 2 + CY),
                   Round(EX + 3 + CX), Round(EY + 3 + CY));

    //ellipse normal direction
    DX := B2 * EX;
    DY := A2 * EY;
    DD := 1.0 / (DY * DY + DX * DX);

    //helper point, projection onto the normal
    FX := DD * (NPX * DX * DX + EX * DY * DY - DY * DX * EY + DX * DY * NPY);
    FY := DD * (-DX * DY * EX + DX * DX * EY + DX * NPX * DY + DY * DY * NPY);

    //mirrored point
    NPX := NPX + 2 * (EX - FX);
    NPY := NPY + 2 * (EY - FY);

    //new velocity components
    DD := V / Hypot(NPX - EX, NPY - EY);
    VX := (NPX - EX) * DD;
    VY := (NPY - EY) * DD;
  end;

  //new position
  PX := NPX;
  PY := NPY;

  //mark new position
  Canvas.Ellipse(Round(PX - 1 + CX), Round(PY - 1 + CY),
                 Round(PX + 1 + CX), Round(PY + 1 + CY));

end;

A = 125,B = 100 从椭圆中心(左图)开始,从右焦点(右图)开始,球到达左焦点,然后返回右焦点

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 2014-05-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多