【问题标题】:How do I rotate a parabola around its origin?如何围绕其原点旋转抛物线?
【发布时间】:2019-06-28 19:38:36
【问题描述】:

我一直在制作高尔夫游戏。我可以很容易地使用运动学方程绘制球的预测运动抛物线。也就是说,我已经隔离了其运动的 x、y 和 z 分量(它是一个 3D 抛物线)。现在我正在尝试在旋转抛物线时如何绘制这条预测线。当 z 分量等于 0 并且抛物线实际上是一条直线时,我已经成功地做到了这一点。当运动中有 z 分量时,我遇到了困难。

我一直在使用这段代码找到z分量抛物线的方程,知道抛物线上的三个点(其中一个总是(0,0)一个是顶点,最后一个(最大距离,0) ):

public void CalcParabolaVertex(float x1, float y1, float x2, float y2, float x3, float y3, out double xv, out double yv)
    {
        double denom = (x1 - x2) * (x1 - x3) * (x2 - x3);
        double A = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / denom;
        double B = (x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1) + x1 * x1 * (y2 - y3)) / denom;
        double C = (x2 * x3 * (x2 - x3) * y1 + x3 * x1 * (x3 - x1) * y2 + x1 * x2 * (x1 - x2) * y3) / denom;

        xv = -B / (2 * A);
        yv = C - B * B / (4 * A);
    } 

知道抛物线 y = ax2 + bx + c 如何编码这条抛物线的旋转?

任何帮助将不胜感激!

【问题讨论】:

  • 问题很不清楚。什么是轴方向? (如果你使用重力)。抛物线是如何定义的?它应该围绕什么旋转?代码片段旨在找到二维抛物线的“顶点” - 它是如何相关的?
  • 我很抱歉不够清楚。球在 3D 空间中移动,但它的侧向速度与 2D 抛物线速度的水平分量相当,因为它具有初始速度,然后随着时间的推移作用力,它在射弹的最大范围内拦截 x。在上面的脚本中,双精度数 A、B 和 C 是 a y = ax2 + bx + c 二次方程中的 a、b 和 c 部分。抛物线始终起源于(0,0),我想围绕原点旋转它。
  • 绕原点旋转 - 在 OXY 平面内?
  • 是的,在 OXY 平面上。

标签: math


【解决方案1】:

编辑:适合矢量绘图的简单方法:

为普通抛物线生成点并围绕原点旋转:

for x with some step:
    y = a * x*x + b *x + c
    rx = x * cos(phi) - y * sin(phi)
    ry = x * sin(phi) + y * cos(phi)
    draw line to rx,ry

德尔福代码:

 var
  aa, bb, cc, y: Double;
  Phi, cs, sn: Double;
  X, xx, yy: Integer;
begin
  X := -300;
  aa := 0.01;
  bb := 0;
  cc := 0;
  Phi := -Pi/4;
  cs := Cos(Phi);
  sn := Sin(Phi);

  while X <= 200 do begin
     y := aa * x * x + bb * x + cc * x;
     xx := Round(200 + x * cs - y * sn);   //+200 to draw in visible region
     yy := Round(200 + x * sn + y * cs);
     if x = -200 then
        Canvas.MoveTo(xx, yy)
     else
        Canvas.LineTo(xx, yy);
     X := X + 10;
  end;

请注意,旋转抛物线不能更多地表示为Y(x)函数(想象抛物线旋转了90度)

二次曲线的一般方程为

 A*x^2 + B*x*y + C*y^2 + D*x + E*y + F = 0

你的情况

 A = a; B,C=0; D=b; E=-1; F=c

矩阵形式的相同一般方程
(参考:Rogers, Adams. Mathematical elements for computer graphics书)

           |A     B/2   D/2 |    |x|
 |x y 1| * |B/2   C     E/2 | *  |y| = 0
           |D/2   E/2   F   |    |1|

或使用我们的系数

           |a     0     b/2 |    |x|
 |x y 1| * |0     0    -1/2 | *  |y| = 0
           |b/2  -1/2   c   |    |1|

要进行旋转,我们必须将中心矩阵乘以左侧的旋转矩阵和右侧的转置旋转矩阵,得到最终方程。
这里cs=Cos(Phi)sn=Sin(Phi)

           |cs  -sn  0 |    |a     0     b/2 |    |cs  sn  0 |   |x|
 |x y 1| * |sn  cs   0 | *  |0     0    -1/2 |  * |-sn cs  0 | * |y| = 0
           |0   0    1 |    |b/2  -1/2   c   |    |0    0  1 |   |1|

如果您有一些符号计算工具,如 Maple、Matematica 等,您可以将这些矩阵相乘并得到结果。也可以用笔和纸获得。

编辑:制作 Maple 乘法

文本中的最后一个表达式:

 (((x*cs+y*sn)*a+1/2*b)*cs+1/2*sn)*x+
 (((x*cs+y*sn)*a+1/2*b)*sn-1/2*cs)*y+
 1/2*(x*cs+y*sn)*b+1/2*x*sn-1/2*y*cs+c

收集x和y的系数,得到一般方程的系数

A = cs * cs * a 
B = 2 * a * cs * sn
C = sn * sn * a
D = cs * b + sn
E = sn * b - cs
F = c

概念证明:Delphi 代码生成旋转 45 度的抛物线

var
  aa, bb, cc, A, B, C, d, E, F: Double;
  Phi, cs, sn: Double;
  X, Y: Integer;
begin
  aa := 0.01;
  bb := 0;
  cc := 0;
  Phi := -Pi / 4;
  cs := Cos(Phi);
  sn := Sin(Phi);
  A := cs * cs * aa;
  B := 2 * aa * cs * sn;
  C := sn * sn * aa;
  d := cs * bb + sn;
  E := sn * bb - cs;
  F := cc;
  for Y := -300 to 300 do
    for X := -300 to 300 do
      if Abs(A * X * X + B * X * Y + C * Y * Y + d * X + E * Y + F) <= 3 then
        Canvas.Pixels[X + 300, Y + 300] := clRed;

【讨论】:

  • 非常感谢您的帮助!您使用 delphi 绘制它的最后一部分特别有用,因为我目前正在使用 unity 绘制它。我试图将其转换为 C#,但遇到了一些问题。如果我理解正确,aa、bb 和 cc 是二次方程的值(y = aax2+ bbx + cc)?我认为我遇到的麻烦是将底部的 do 循环转换为 c# 的 for 循环。如果你知道怎么做,你能帮忙吗?否则再次感谢,您提供了很多帮助!
  • y = aa*x2+ bb*x + cc - 是的。 Loop 等价于for(int y=-300; y&lt;301; y++) 此图像显示了接近抛物线的点。很难将这样的图像转换为矢量图。为此,我添加了另一种方法
  • 所以我首先做了正确的 c# 转换,现在 for 循环中的
  • 矢量绘图是另一种方式 - 计算基本抛物线的点并旋转它们。
  • 我添加了简单绘图的代码。注意 - 绘制曲线就足够了。我的第一种方法是提供方程式。
猜你喜欢
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多