#java #math #trigonometry
Вопрос:
У меня есть что-то вроде следующего: Введите x, y и h, чтобы получить ориентацию панорамирования и наклона
double dz = Math.sqrt( x*x y*y );
double rotPan = Math.toDegrees(Math.atan(x / y));
double rotTilt = Math.toDegrees(Math.atan( h / dz ));
Можно ли обратить вспять эффект математики только с помощью h, заданного в начальной точке, и достичь начальных значений x и y?
Комментарии:
1. Помимо вашего вопроса: используйте
Math.hypot(x, y)
вместоMath.sqrt(x * x y * y)
иMath.atan2(x, y)
вместоMath.atan(x / y)
(то же самое для другого atan).2. Тх, я их поменял. Все еще заинтересован в обратном к x/y 🙂
3. Это просто перестановка уравнений. Сделайте это на бумаге, это будет намного проще.
Ответ №1:
double x = dz * Math.sin(Math.toRadians(rotPan));
double y = dz * Math.cos(Math.toRadians(rotPan));
К сожалению, полностью восстановить исходные значения не представляется возможным.
Например, x = 2 и y = 5 дадут вам точно такой же dz, rotPan (и rotTilt, который не нужен), как x = -2 и y = -5. Поэтому лучшее, что вы можете сделать, — это восстановить (x, y) с возможным изменением знака для обеих координат. Кстати, вы могли бы избежать этой проблемы, если бы использовали функцию atan2 вместо atan:
double dz = Math.hypot(x, y);
double rotPan = Math.toDegrees(Math.atan2(x, y));
double rotTilt = Math.toDegrees(Math.atan2(h, dz));
Если вы используете приведенные выше формулы для расчета rotPan и rotTilt, то формулы в верхней части моего поста всегда будут давать вам начальные координаты (с ограничениями числовых ошибок).
Комментарии:
1. Да, теперь это работает, спасибо. Придется поменять cos на x и sin на y, но теперь это работает как зачарованное. Это легко, если вы знаете, как 😉
Ответ №2:
Все, что вам нужно сделать, это переставить уравнения.
double dz = Math.sqrt( x*x y*y );
double rotPan = Math.toDegrees(Math.atan(x / y));
double rotTilt = Math.toDegrees(Math.atan( h / dz ));
Учитывая rotTilt
, что вы можете рассчитать соотношение h
к dz
:
double hOverDz = Math.tan(Math.toRadians(rotTilt));
Так что , если вы знаете h
, вы можете рассчитать dz
:
dz = h / Math.tan(Math.toRadians(rotTilt));
Учитывая rotPan
, что вы можете рассчитать соотношение x
к y
:
double xOverY = Math.tan(Math.toRadians(rotPan));
так:
x = y * xOverY;
Подзаголовок и перестановка:
dz = sqrt(y^2 * xOverY^2 y*y)
= sqrt((xOverY^2 1) * y*y)
dz = y * sqrt(1 xOverY^2)
y = dz / sqrt(1 xOverY^2)
= h / (tan(rotTilt) * sqrt(1 xOverY^2))
y = h / tan(rotTile) * sqrt(1 tan(rotPan)^2))
следовательно
x = y * xOverY
= (h / tan(rotTile) * sqrt(1 tan(rotPan)^2))) * tan(rotPan)
Комментарии:
1. Это было нелегко понять, потому что я не математик, но я думаю, что у меня есть решение.
Ответ №3:
После ввода информации от Энди Тернера и выяснения того, что именно это означает, я получил:
double dz = h / Math.tan(Math.toRadians(rotTilt));
double xOverY = Math.tan(Math.toRadians(rotPan));
double x = Math.round(dz / Math.sqrt(1 xOverY*xOverY));
double y = Math.round(x * xOverY);
if (pan > 90 || pan < 0) { x *=-1; y *=-1; } // sign correction if angel > 90 or < 0
Я не знаю, есть ли другой способ из-за неправильного результата, если ангел > 90 или >
ПРАВКА: Хорошо, это не работает. Если я поставлю rotPan = 90 и rotTilt = любой, dx и dy всегда будут равны 0
Я не понимаю вашего способа решения или что-то не так.
Комментарии:
1. Если rotTilt = 90, это означает, что арктан h/dz равен 90 градусам, но это означает, что h/dz-положительная бесконечность. Поэтому неудивительно, что это означает, что dz = 0, поэтому и dx, и dy являются нулями. Другими словами, вы не можете получить rotTilt = 90 для любых ненулевых dx и dy (ну, если только h не является положительной бесконечностью….)
2. Моя ошибка: Я имею в виду ротПан, а не ротТилт.