A A A A Автор Тема: Делаю приложение наподобии Google Earth, и хочу спросить совета по оптимизации.  (Прочитано 890 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich
Доброго времени года!
В программе земля, или возможно любая другая планета или небесное тело солнечной системы находится в центре трехмерных декартовых координат, а ось мира соответствует вектору (0,1,0). Я могу точно располагать объекты на поверхности планеты по географическим координатам.
Теперь у меня стоит задача по введенной дате и времени суток(UTC) разместить Солнце относительно Земли, так чтобы оно располагалось максимально приемлемо к реальности.
1.Разбираясь в материале, я обнаружил что расчет эфемерид, для такого дела  разнообразен, по точности и производительности. Поэтому обращаюсь к вам за советом, какой метод лучше всего использовать для расчета положения Солнца, Луны, других планет и возможно искусственных спутников, при условии что программа работает в реальном времени, и чтобы была приемлемая точность для скажем модельных испытаний.
2.Какой алгоритм должен работать для размещения источника света(Солнца) в пространстве относительно земли как начала координат по конкретной дате времени суток? Я себе представляю, что нужно вычислить восхождение и склонение Солнца в конкретную дату время суток, и при помощи неких формул преобразовать полученные координаты в декартовые трехмерные и разместиь в них Солнце. Я правильно понимаю?
Спасибо!

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
Для всего, кроме спутников, достаточно минимальной точности, если не стоит задачи точной визуализации, например, затмений.
Достаточно странно у Вас выбрана система координат. Тяжело будет в ней оперировать астрономическими вычислениями. Имеете шанс просто запутаться. Далее, угловые размеры планет будут мизерными, а координаты будут велики. Так, расстояние от Земли до Солнца, выраженное в радиусах Земли, будет составлять 23455 плюс-минус 1,7%. До Юпитера от 10 тысяч до 14,5 тысяч и т.д.
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich
Конечно в планах заняться спутниками, но для затравки надо разобраться с обращением солнца и других планет, лучше сказать определения расположения планет во времени относительно Земли. И здесь мне пока не понятно за что браться, каким координатами пользоваться. Т.е. имея дяту и время суток, что я должен рассчитать, чтобы потом разместить это в прямоугольных координатах(ECEF). Собственно с этим вопросом я обращаюсь.

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
Если пишете на C++, то можете взять библиотеки из книги Т.Пфлегера и О.Монтенбрука "Астрономия на персональном компьютере".
Это называется вычисление эфемерид планет.
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich
Я заметил, что в книге монтебрука и в исходниках движка целестии время TAI рассчитывается до секунд, т.е. там нет упоминания о миллисекундах. Т.е. важны ли миллисекунды? Если я всетаки хочу большую точность, для рассчетов не ограничиваясь лишь секундами. Т.е. это важно иметь возможность учитывать миллисекунды?

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
Положение планет и Солнца в сферических координатах можно хоть в пределах часа интерполировать какой-нибудь гладкой функцией. Там изменения медленные и производные любых порядков непрерывны.
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich
А касательно естественных спутников? Например я хочу моделировать вращение спутника вокруг земли, у меня есть начальные параметры, эпоха, скорость, в этом случае миллисекунды имеют значение, или их тоже можно интерполировать?

Правильно ли я понимаю, что для того чтобы разместить землю относительно солнца, я сделаю так грубо говоря:
1 Найду положение планеты относительно солнца в эклиптических координатах, т.е. на плоскостти эклиптики
2. Наклоню планету относительно плоскости эклиптики
3 т.к. планета у меня в начале координат, я отодвину солнце от планеты на расстояние орбиты, найденное в п.1

А модель для расчетов орбит и координат я использую VSOP87 ?

Как вы считаете это хороший вариант?

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
Я сомневаюсь, что Вам нужна действительно высокая точность представления координат, поэтому при выборе модели лучше отдать преимущество её простоте и скорости вычислений, а не точности. Заменить модель, я думаю, проблем не составит, если Вы прикрутите к ней один уровень абстракции.
Эфемериды планет считаются сначала в орбитальной гелиоцентрической системе координат, потом переводятся в эклиптическую гелиоцентрическую систему координат, потом выполняется переход в эклиптическую геоцентрическую систему коодинат, дальше в экваториальную геоцентрическую, дальше, если надо, в экваториальную топоцентрическую (но Вам вряд ли этот шаг нужен), потом, если надо, в горизонтальную топо- или геоцентрическую, в зависимости от прошлого шага.
То есть расчёт всегда ведётся в той системе координат, которая наиболее естественно и коротко описывает текущие вычисления, дальше выполняется переход к следующей СК, на которой естественным образом выполняется следующий шаг, и т.д.
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
Если у Вас исходники под руками, можете показать прототип функции преобразования даты в некоторую непрерывную шкалу? Скорее всего там будут юлианские дни. Может быть проблемы с долями секунд там просто нет.
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich
Со временем я тоже пока не решил, думал про такой код, но разбираясь в исходниках других приложений думаю переделать. Сейчас это выглядит так:
og.dateTime.SECONDS_PER_MILLISECOND = 0.001;
og.dateTime.SECONDS_PER_MINUTE = 60.0;
og.dateTime.MINUTES_PER_HOUR = 60.0;
og.dateTime.HOURS_PER_DAY = 24.0;
og.dateTime.SECONDS_PER_HOUR = 3600.0;
og.dateTime.SECONDS_PER_12_HOURS = 12.0 * og.dateTime.SECONDS_PER_HOUR;
og.dateTime.MINUTES_PER_DAY = 1440.0;
og.dateTime.SECONDS_PER_DAY = 86400.0;
og.dateTime.DAYS_PER_JULIAN_CENTURY = 36525.0;
og.dateTime.PICOSECOND = 0.000000001;
og.dateTime.MODIFIED_JULIAN_DATE_DIFFERENCE = 2400000.5;
og.dateTime.TDT_TAI = 32.184;
og.dateTime.GPS_TAI = -19.0;
og.dateTime.J2000 = 2451545;
og.dateTime.EPOCH = new og.dateTime.JulianDate(og.dateTime.J2000, 0.0);


og.dateTime.JulianDate = function (dayNumber, secondsOfDay) {
    this._dayNumber = dayNumber || 0;
    this._secondsOfDay = secondsOfDay || 0;
    this.set(dayNumber, secondsOfDay);
};

og.dateTime.JulianDate.getDayNumber = function (year, month, day) {
    var a = ((month - 14) / 12) | 0;
    var b = year + 4800 + a;
    return (((1461 * b) / 4) | 0) + (((367 * (month - 2 - 12 * a)) / 12) | 0) -
        (((3 * (((b + 100) / 100) | 0)) / 4) | 0) + day - 32075;
};

og.dateTime.JulianDate.getSecondsOfDay = function (hour, minute, second, millisecond) {
    hour = hour - 12;
    if (hour < 0) {
        hour += 24;
    }
    return second + ((hour * og.dateTime.SECONDS_PER_HOUR) + (minute * og.dateTime.SECONDS_PER_MINUTE) +
        (millisecond * og.dateTime.SECONDS_PER_MILLISECOND));
};

og.dateTime.JulianDate.compare = function (left, right) {
    var d = left._dayNumber - right._dayNumber;
    if (d !== 0) {
        return d;
    }
    return left._secondsOfDay - right._secondsOfDay;
};

og.dateTime.JulianDate.fromDate = function (date) {
    var dayNumber = og.dateTime.JulianDate.getDayNumber(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate());
    var secondsOfDay = og.dateTime.JulianDate.getSecondsOfDay(date.getUTCHours(), date.getUTCMinutes(),
        date.getUTCSeconds(), date.getUTCMilliseconds());
    if (secondsOfDay >= og.dateTime.SECONDS_PER_12_HOURS) {
        dayNumber--;
    }
    var res = new og.dateTime.JulianDate(dayNumber, secondsOfDay);
    return res.convertUtcToTai();
};

og.dateTime.JulianDate.now = function () {
    return og.dateTime.JulianDate.fromDate(new Date());
};

og.dateTime.JulianDate.prototype.setDayNumber = function (dayNumber) {
    this._dayNumber = dayNumber;
    return this;
};

og.dateTime.JulianDate.prototype.setSecondsOfDay = function (secondsOfDay) {
    return this.set(this._dauNumber, secondsOfDay);
};

og.dateTime.JulianDate.prototype.getDayNumber = function () {
    return this._dayNumber;
};

og.dateTime.JulianDate.prototype.getSecondsOfDay = function () {
    return this._secondsOfDay;
};

og.dateTime.JulianDate.prototype.set = function (dayNumber, secondsOfDay) {
    var extraDays = secondsOfDay / og.dateTime.SECONDS_PER_DAY | 0;
    dayNumber += extraDays;
    secondsOfDay -= og.dateTime.SECONDS_PER_DAY * extraDays;

    if (secondsOfDay < 0) {
        dayNumber--;
        secondsOfDay += og.dateTime.SECONDS_PER_DAY;
    }

    this._dayNumber = dayNumber;
    this._secondsOfDay = secondsOfDay;

    return this;
};

og.dateTime.JulianDate.prototype.addSeconds = function (seconds) {
    return this.set(this._dayNumber, this._secondsOfDay + seconds);
};

og.dateTime.JulianDate.prototype.toDate = function () {

    var thisUtc = this.convertTaiToUtc();
    if (!thisUtc) {
        this.addSeconds(-1);
        thisUtc = this.convertTaiToUtc();
    }

    var julianDayNumber = thisUtc._dayNumber;
    var secondsOfDay = thisUtc._secondsOfDay;

    if (secondsOfDay >= og.dateTime.SECONDS_PER_12_HOURS) {
        julianDayNumber++;
    }

    var L = (julianDayNumber + 68569) | 0;
    var N = (4 * L / 146097) | 0;
    L = (L - (((146097 * N + 3) / 4) | 0)) | 0;
    var I = ((4000 * (L + 1)) / 1461001) | 0;
    L = (L - (((1461 * I) / 4) | 0) + 31) | 0;
    var J = ((80 * L) / 2447) | 0;
    var day = (L - (((2447 * J) / 80) | 0)) | 0;
    L = (J / 11) | 0;
    var month = (J + 2 - 12 * L) | 0;
    var year = (100 * (N - 49) + I + L) | 0;

    var hour = (secondsOfDay / og.dateTime.SECONDS_PER_HOUR) | 0;
    var remainingSeconds = secondsOfDay - (hour * og.dateTime.SECONDS_PER_HOUR);
    var minute = (remainingSeconds / og.dateTime.SECONDS_PER_MINUTE) | 0;
    remainingSeconds = remainingSeconds - (minute * og.dateTime.SECONDS_PER_MINUTE);
    var second = remainingSeconds | 0;
    var millisecond = ((remainingSeconds - second) / og.dateTime.SECONDS_PER_MILLISECOND);

    hour += 12;
    if (hour > 23) {
        hour -= 24;
    }

    return new Date(Date.UTC(year, month - 1, day, hour, minute, second, millisecond));
};

og.dateTime.JulianDate.secondsDifference = function (left, right) {
    return ((left._dayNumber - right._dayNumber) * og.dateTime.SECONDS_PER_DAY +
        (left._secondsOfDay - right._secondsOfDay));
};

og.dateTime.JulianDate.daysDifference = function (left, right) {
    return left._dayNumber - right._dayNumber +
        (left._secondsOfDay - right._secondsOfDay) / og.dateTime.SECONDS_PER_DAY;
};

og.dateTime.JulianDate._compareLeapSecondDates = function (dateToFind, leapSecond) {
    return og.dateTime.JulianDate.compare(dateToFind, leapSecond[0]);
};

og.dateTime.JulianDate.prototype.getTotalDays = function () {
    return this._dayNumber + (this._secondsOfDay / og.dateTime.SECONDS_PER_DAY);
};

og.dateTime.JulianDate.prototype.convertUtcToTai = function () {
    var leapSeconds = og.dateTime.JulianDate.leapSecondsTable;
    var index = og.utils.binarySearch(leapSeconds, this, og.dateTime.JulianDate._compareLeapSecondDates);

    if (index < 0) {
        index = ~index;
    }

    if (index >= leapSeconds.length) {
        index = leapSeconds.length - 1;
    }

    var offset = leapSeconds[index][1];
    if (index > 0) {
        if (og.dateTime.JulianDate.secondsDifference(leapSeconds[index][0], this) > offset) {
            index--;
            offset = leapSeconds[index][1];
        }
    }

    return this.addSeconds(offset);
};
og.dateTime.JulianDate.prototype.clone = function () {
    return new og.dateTime.JulianDate(this._dayNumber, this._secondsOfDay);
};

og.dateTime.JulianDate.prototype.getTdb = function () {
    var res = this.clone();
    res.addSeconds(og.dateTime.TDT_TAI);
    var g = 6.239996 + 0.0172019696544 * (res.getTotalDays() - og.dateTime.J2000);
    return res.addSeconds(0.001658 * Math.sin(g + 1.671e-2 * Math.sin(g)));
};

og.dateTime.JulianDate.prototype.convertTaiToUtc = function () {
    var leapSeconds = og.dateTime.JulianDate.leapSecondsTable;
    var index = og.utils.binarySearch(leapSeconds, this, og.dateTime.JulianDate._compareLeapSecondDates);
    if (index < 0) {
        index = ~index;
    }

    if (index === 0) {
        return this.addSeconds(-leapSeconds[0][1]);
    }

    var difference = og.dateTime.JulianDate.secondsDifference(leapSeconds[index][0], this);

    if (difference === 0) {
        return this.addSeconds(-leapSeconds[index][1]);
    }

    if (difference <= 1.0) {
        return null;
    }

    return this.addSeconds(-leapSeconds[index - 1][1]);
};

og.dateTime.JulianDate.leapSecondsTable = [
    [new og.dateTime.JulianDate(2441317, 43210.0), 10.0], // 1972-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2441499, 43211.0), 11.0], // 1972-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2441683, 43212.0), 12.0], // 1973-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2442048, 43213.0), 13.0], // 1974-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2442413, 43214.0), 14.0], // 1975-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2442778, 43215.0), 15.0], // 1976-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2443144, 43216.0), 16.0], // 1977-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2443509, 43217.0), 17.0], // 1978-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2443874, 43218.0), 18.0], // 1979-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2444239, 43219.0), 19.0], // 1980-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2444786, 43220.0), 20.0], // 1981-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2445151, 43221.0), 21.0], // 1982-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2445516, 43222.0), 22.0], // 1983-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2446247, 43223.0), 23.0], // 1985-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2447161, 43224.0), 24.0], // 1988-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2447892, 43225.0), 25.0], // 1990-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2448257, 43226.0), 26.0], // 1991-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2448804, 43227.0), 27.0], // 1992-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2449169, 43228.0), 28.0], // 1993-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2449534, 43229.0), 29.0], // 1994-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2450083, 43230.0), 30.0], // 1996-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2450630, 43231.0), 31.0], // 1997-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2451179, 43232.0), 32.0], // 1999-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2453736, 43233.0), 33.0], // 2006-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2454832, 43234.0), 34.0], // 2009-01-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2456109, 43235.0), 35.0], // 2012-07-01T00:00:00.000Z
    [new og.dateTime.JulianDate(2457204, 43236.0), 36.0]  // 2015-07-01T00:00:00.000Z
];

Здесь юлианская дата изначально в ТАI. И хранит дни и секунды дня. Но возможно это не лучшее решение, пока не понял...
Вообще мне нравится идея учитывать доли секунды, но не могу понять целесообразность в плане точности на будущее.

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
А в чём проблема хранить секунду с долями?
og.dateTime.SECONDS_PER_MILLISECOND = 0.001;А вот это сильно ;D
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich
Это правила хорошего тона в программировании. Эта структура позволяет хранить доли секунды, в отличии от тех что я встречал типа 2555654.41345. Вы спросили про шкалу которую я использую и я ответил. В расчетах эфемерид доли секунды не используются, в тех алгоритмах, что я встречал(celestia и т.д.), а т.к. у меня стоит задача расчета положения по дате и времени, то меня наверное не сильно интересует 86400 кадров для каждой секунды вокруг Земли Луны и т.д. Но эта шкала должна была бы использоваться и для расчетов движения по орбитам. Возможно в этом есть смысл.
 т.к. я профан в астрономической математике, то во первых интересуюсь здесь какими способами рассчитывается положение относительно солнца в 3х мерном пространстве, и необходимость использования долей секунды.

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
2555654.41345
Здесь доли суток. Секунда - примерно 5 знаков после запятой, миллисекунда - 8. Главное чтобы точности типа данных хватало, а типа 64-битного вещественного числа (double) хватает для представления с погрешностью примерно 25 мкс.
Это правила хорошего тона в программировании.
Справедливо, но как-то очень многословно выражено. Впрочем это к теме не имеет отношения.
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
Вам дальше нужна библиотека для пересчёта прямоугольных координат в сферические и обратно, и для манипуляций с разворотами. Очень хорошо это описано у Пфлегера и Монтенбрука. Дальше вся математика - только умножение матриц, векторов и скаляров, а также сложение векторов.
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/

Оффлайн mgevlichАвтор темы

  • Новичок
  • *
  • Сообщений: 8
  • Благодарностей: 0
  • Мне нравится этот форум!
    • Сообщения от mgevlich
Благодарю, за совет. Книгу скачал. Переделываю JD на double. Так выглядит приятнее. Спасибо.

Оффлайн xd

  • *****
  • Сообщений: 17 982
  • Благодарностей: 378
    • Skype - deimos.belastro.net
  • Награды Открытие комет, астероидов, сверхновых звезд, научно значимые исследования.
    • Сообщения от xd
    • Белорусская любительская астрономическая сеть
У природы нет плохой погоды, у неё просто на нас аллергия.

Учение без размышления бесполезно, но и размышление без учения опасно /Конфуций/
Слово есть поступок. /Л. Толстой/