Как прогнозировать столкновения между судном и сферой влияния тела в 2D - программирование
Подтвердить что ты не робот

Как прогнозировать столкновения между судном и сферой влияния тела в 2D

Длительный прослушиватель, первый раз. Я делаю небольшую хобби в XNA, ее о транспортных кораблях в космосе, аналогичных контейнерным судам в море. Мне нужно уметь предсказать встречу между судами и планету/лунами кеплеровых орбитальных элементов. Корабль и тело вращаются вокруг того же центра притяжения.

Подход, который я разработал до сих пор, - это сначала сделать предварительные проверки апоапсиса и периапсиса (самые дальние и самые близкие точки из центра притяжения), чтобы увидеть, возможно ли встреча. Между проверками, такими как это, и если орбита судна открыта (гиперболическая, я приближаю случай параболы к гиперболе), она может исключать многие сценарии, где не может быть встречи.

Если эти проверки определяют возможность встречи, я определяю минимальное и максимальное расстояние от центра притяжения, которое судно имеет право на встречу. Затем я получаю точки пересечения орбиты корабля с двумя кругами, определяемыми этим минимумом и максимумом. Это приводит к нулю, двум или четырем точкам на орбите судна, определяя нулевой, один или два периода, когда он может столкнуться с сферой тела. В этом случае, если есть нулевые пересечения, возможно, что вся орбита судна находится в зоне встречи, это, вероятно, необычный крайний случай, но нужно будет покрыть.

Я могу получить время, когда корабль будет передавать эти точки на этой орбите, давая один или два окна времени для проверки на встречу, но оттуда мое лучшее решение выполняет поиск временного промежутка, деля его на этапы, вычисляя Положение тела в это время, а затем тестирование для встречи.

Проблема с этим подходом заключается в знании размера, чтобы сделать шаги для эффективного поиска встречи. Получение положения тела вовремя несколько дорого, поэтому я предпочел бы сделать это как можно меньше, но слишком большие шаги могут потенциально пропустить встречу.

Существуют ли какие-либо свойства конфокальных конических форм, которые могли бы помочь уменьшить пространство поиска? Или существуют другие способы предсказать столкновение/столкновение между тем, что эффективно является точкой, движущейся вдоль конического пути, и кругом, движущимся вдоль эллипса, разделяющим координационную точку.

4b9b3361

Ответ 1

Используйте радиальное обнаружение столкновений (круги), с одним кругом, представляющим влияние гравитации планеты (будет больше, чем сама планета), другой круг для каждого корабля и заставит центральную точку каждого круга двигаться друг к другу в прямая линия настолько незначительно, насколько уменьшается расстояние.

Примените количество притяжения каждого круга к скорости движения каждого корабля. Движение может быть выполнено с помощью простого триггера, cos() для x, sin() для y, нет необходимости в более сложной математике. Когда расстояние между любыми двумя объектами меньше суммы их радиусов, возникает столкновение.

Но когда вы делаете эту форму столкновения только на "кругах силы тяжести", так сказать, когда они сталкиваются, вы можете увеличить скорость корабля на небольшое количество каждой итерации, чтобы имитировать тягу силы тяжести.

Ответ 2

Вы можете попытаться построить функцию, описывающую (квадрат) расстояния между планетой и судном, как функцию времени, используя обычное выражение расстояния Пифагора. Вы ищете нули этой функции, поэтому метод Ньютона или аналогичный может быть применен для их поиска.

Это должно хорошо работать при условии, что движение планеты намного медленнее, чем корабль, - тогда функция будет относительно гладкой, и метод Ньютона не будет иметь проблем с сближением. Однако, если движение планеты намного быстрее, чем у корабля, то эта функция расстояния будет отскакивать вверх и вниз, как "spring", наложенная на некоторую параболоподобную кривую и, возможно, несколько раз пересекает ось x. Метод Ньютона может иметь проблемы с такими функциями, где производная быстро меняет направление.

Надеемся, что некоторые термины будут отменены, когда вы построите функцию расстояния, или выражение может быть упрощено или аппроксимировано иначе, но если этого не достаточно, то можно найти нули в вертикальном и горизонтальном направлениях. (Фактически вы могли выбирать расстояния вдоль любой оси - например, на большой оси орбиты планеты.) Нули в любой из этих функций необходимы, но не достаточные условия для столкновения, и их проще рассчитать. Если у вас есть список нулевых координат x, отсортированных по времени, и то же самое для нулей y-направления, вы можете найти любые истинные столкновения, вычислив их пересечение с объединением списков (a la mergesort).

Ответ 3

Поскольку на этот вопрос еще не принято ответа, и я не вижу приведенных ниже расчетов, я добавлю их в надежде, что это кому-нибудь поможет. Я не выяснил, как получить дату, но я выяснил, как получить углы. Это даст вам расстояние между орбитальным телом и кораблем (или кораблем), если вы знаете угол:

public static double RadiusAtAngle(double angle, double semiLatusRectum, double eccentricity)
{
    return semiLatusRectum / (1 + eccentricity * Math.Cos(angle)); 
}

Что еще более важно, переключение этого calc дает вам угол к краю сои, если вы знаете semiLatusRectum и эксцентриситет (радиус здесь будет расстоянием от тела до края сои):

public static double AngleAtRadus(double radius, double semiLatusRectum, double eccentricity)
{
    //r = p / (1 + e * cos(θ))
    //1 + e * cos(θ) = p/r
    //((p / r) -1) / e = cos(θ)
    return Math.Acos((semiLatusRectum / radius - 1) / eccentricity);
}

Для справки, semiLatusRectum можно найти по полу-оси и эксцентриситету:

public static double SemiLatusRectum(double SemiMajorAxis, double eccentricity)
{
    if (eccentricity == 0)//ie a circle 
        return SemiMajorAxis;
    return SemiMajorAxis * (1 - eccentricity * eccentricity);
}

Обратите внимание, что эти вычисления также будут работать для гиперболических траекторий.