Как вращать параболу вокруг ее источника? - PullRequest
0 голосов
/ 05 февраля 2019

Я возился с игрой в гольф.Я могу нарисовать предсказанную параболу движения шариков, используя кинематические уравнения достаточно легко.То есть я выделил x, y и z составляющие его движения (это трехмерная парабола).Теперь я пытаюсь понять, как нарисовать эту линию предиктора, когда я вращаю параболу.Я успешно делал это, когда компонент 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 как мне кодировать вращение этой параболы?

Любая помощь будет принята с благодарностью!

1 Ответ

0 голосов
/ 05 февраля 2019

Редактировать: простой метод, подходящий для векторного рисования:

Создание точек для обычной параболы и вращение их вокруг начала координат:

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

Код Delphi:

 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 и т. д., вы можете умножить эти матрицы и получить результат.Его также можно получить ручкой и бумагой.

Редактировать: сделано умножение клена enter image description here

Последнее выражение в тексте:

 (((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;

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...