Если тема актуальна, то вот мой вариант:
класс планеты:
TPlanet = class {планеты}
public
C_RADIUS,
C_MASS,
C_SID, // сидерический
C_SIN, // синодический
C_AFEL, // афелий
C_PERIG, // перигелий
C_EX : extended; // эксцентриситетик)
NamePlanet : string;
MaxX, MaxY, // максимальная и минимальная полуоси эллипсоидной орбиты
TurnTime, OrbiTime : single; // периоды оборота вокрут своей оси и Солнца
PrevPos,
NowPos,
FuturePos : TAffineVector; // позиции относительно цены деления времени(скорости) предыдущая, текущая и буд.
end;
все параметры планет задавал как константы и использовал при создании классов планет относительно имени указанной планеты, например:
MARS_RADIUS = 3376.2e3; {метр}
MARS_MASS = 6.4185e23; {килограмм}
MARS_SID = 1.88 * EARTH_SID;
MARS_SIN = 779.94 * 24 * 60; {минут} {синодический - вокруг своей оси}
MARS_AFEL = 249.23e9; {метр}
MARS_PERIG = 206.62e9; {метр}
MARS_EX = 0.0935;
или наприер Церера:
CERES_RADIUS = 940000; {примерно} {метр}
CERES_MASS = 9.5e20; {килограмм}
CERES_SID = 4.6 * EARTH_SID; {так же относится ко всему поясу астероидов}
CERES_SIN = 0; {минут} {синодический - вокруг своей оси}
CERES_AFEL = 2.85 * 149597870610; {метр}
CERES_PERIG = 2.54 * 149597870610;
CERES_EX = 0.08;
а так же такие параметры для координат в программе как масштаб:
MASHTAB = 1e6; // физический масштаб
затем создавал все планеты в списке и проматывал их каждый шаг времени, при этом как планета проходила полный период вокруг себя или солнца, то я сбрасывал параметры её собственного времени(относительно него я отталкиваюсь в следующем вычислении и т.д.)
кусок кода расчёта координат:
// движение небесных тел
Sun.TurnAngle := MyTime.hour * 360/84960; // Солнце вокруг своей оси
for i:=1 to PlanetList.Count-1 do
begin
// сначало высчитываю личное новое время оборота вокруг себя и на орбите
TPlanet(PlanetList.Items
).TurnTime := TPlanet(PlanetList.Items).TurnTime + IncTime -
trunc( TPlanet(PlanetList.Items).TurnTime/TPlanet(PlanetList.Items).C_SIN ) *
TPlanet(PlanetList.Items).C_SIN;
TPlanet(PlanetList.Items).OrbiTime := TPlanet(PlanetList.Items).OrbiTime + IncTime -
trunc( TPlanet(PlanetList.Items).OrbiTime/TPlanet(PlanetList.Items).C_SID ) *
TPlanet(PlanetList.Items).C_SID;
// а затем реально поворачиваю планету вокруг себя и ставлю в новую координату
TPlanet(PlanetList.Items).Planet.TurnAngle :=
TPlanet(PlanetList.Items).TurnTime * 360/TPlanet(PlanetList.Items).C_SIN;
// сохраняю текущее положение как прошлое
TPlanet(PlanetList.Items).PrevPos[0] := TPlanet(PlanetList.Items).Planet.AbsolutePosition[0];
TPlanet(PlanetList.Items).PrevPos[1] := TPlanet(PlanetList.Items).Planet.AbsolutePosition[1];
TPlanet(PlanetList.Items).PrevPos[2] := TPlanet(PlanetList.Items).Planet.AbsolutePosition[2];
// х
TPlanet(PlanetList.Items).PlanetOwner.Position.X := TPlanet(PlanetList.Items).MaxX *
Cos(GToRad( TPlanet(PlanetList.Items).OrbiTime * 360/TPlanet(PlanetList.Items).C_SID ));
// y
TPlanet(PlanetList.Items).PlanetOwner.Position.Z := -TPlanet(PlanetList.Items).MaxY *
Sin(GToRad( TPlanet(PlanetList.Items).OrbiTime * 360/TPlanet(PlanetList.Items).C_SID ));
// а z = 0 потому что я относительную систему координат планеты уже наклонил на угол её эклиптики относительно главной, т.е. она вращается по 2D эллипссу в наклоненой плоскости)
TPlanet(PlanetList.Items).PlanetOwner.Position.Y := 0;
TPlanet(PlanetList.Items).NowPos[0] := TPlanet(PlanetList.Items).Planet.AbsolutePosition[0];
TPlanet(PlanetList.Items).NowPos[1] := TPlanet(PlanetList.Items).Planet.AbsolutePosition[1];
TPlanet(PlanetList.Items).NowPos[2] := TPlanet(PlanetList.Items).Planet.AbsolutePosition[2];
// высчитываю будущие координаты, с помощью разницы расчётов текущих и будущих, можно лучше заметить смысл формул) ибо я их сам выводил.
TPlanet(PlanetList.Items).FuturePos[0] :=
TPlanet(PlanetList.Items).MaxX *
Cos(GToRad( ( TPlanet(PlanetList.Items).OrbiTime + IncTime -
trunc( TPlanet(PlanetList.Items).OrbiTime/TPlanet(PlanetList.Items).C_SID ) *
TPlanet(PlanetList.Items).C_SID ) * 360/TPlanet(PlanetList.Items).C_SID ));
TPlanet(PlanetList.Items).FuturePos[1] := 0;
TPlanet(PlanetList.Items).FuturePos[2] :=
-TPlanet(PlanetList.Items).MaxY *
Sin(GToRad( (TPlanet(PlanetList.Items).OrbiTime + IncTime -
trunc( TPlanet(PlanetList.Items).OrbiTime/TPlanet(PlanetList.Items).C_SID ) *
TPlanet(PlanetList.Items).C_SID) * 360/TPlanet(PlanetList.Items).C_SID ));
end;
изначальное положение я находил так:
узнал что за главную космическую ось была выбрана ось пересекающая Землю в осеннее равноденствие в 2000 году, я решил расставить все планеты в эту дату в программе как в начальное положение.
на сайте наса я ввёл дату в их калькулятор и потом транспортиром вымерял углы к оси других планет, вот так и парился) а потом относительно тех положений высчитываю положения в любую дату по вышеприведённым формулам.
погрешности наверное на пару десятков тысяч километров, но не страшно для примерного отображения)
потом сверял взаимное расположение с тем же калькулятором наса - всё ровно даже в 2800 году.
вот наглядный пример работы:
http://95.129.163.190:23433/sys/sys.rar (доступно для скачивания в основном по вечерам)
PS:
т.к. сейчас делаю совершенно улучшенный вариант системы, то приведённые здесь ссылки расчётов для меня просто находка, которую я искал 3 дня - парился, поэтоу спасибо.)