Я подумал, что интересно будет осуществить нечто подобное на JS. Было решено отчасти использовать готовую библиотеку LibCanvas из-за её продуманного синтаксиса, что было важно при написании объёмных приложений.
Первая проблема, с которой я столкнулся — это довольно большое количество звёзд, которое требуется отобразить с высокой точностью — их около 6 000. Здесь я решил при помощи несложного PHP-скрипта сгенерировать из текстового файла каталога звёзд массив для js.
Когда использовать LibCanvas?
Собственно стал вопрос; стоит ли всегда использовать LibCanvas? Дело в том, что в проекте кроме самой карты, должен отрисовываться коллаж видимых размеров планет, который предполагал написание отдельной библиотеки и для этой задачи я решил не использовать LibCanvas.
Библиотека математических и астрономических функций
Проект требовал многократного использования разных математических функций, поэтому решено было написать библиотеку этих самых функций.
Собственно, вот результат.
Там соответсвенно:
- Тригонометрические функции с градусным аргументом
- Функции преобразования юлианского дня в григорианскую дату
- Функции перевода горизонтальных/экваториальных координат
- Вычисление атмосферной рефракции
- Прочие (названия месяцев, получение текущего времени и т.д.)
Каталоги данных
База данных объектов в основном находиться здесь
Так же здесь находятся элементы орбит планет и комет.
Отображение звёздочек
for (var i = 0; i < (stars.length); i++){ var decr=stars[i][1]; //Склонение var tr=sr-stars[i][0]; //Прямое восхождение var zl=atmospheric_refraction(equatorial_to_horizontal(decr, tr, phi)[1]);//Зенитное расстояние var mag=Math.round(stars[i][2]/100); //Магнитуда if (zl<90 && mag<magmax){//Все звезды, которые выше горизонта var r_star=k1*1+k2*(magmax-mag); var Az=equatorial_to_horizontal(decr, tr, phi)[0]; //Азимут var cor1=to_xy(zl,Az); Функция рассчета положения звезды var x=(cor1[0]*1).toFixed(0); //Абцисс координата var y=(cor1[1]*1).toFixed(0); //Ординат /* У ярких звёздочек рисуем гало */ if (mag<1.5){ var circl3 = new LC.Circle( x,y,r_star*2); ct.fill(circl3, ct .createRadialGradient( new LC.Circle(x, y, 1), new LC.Circle(x, y, r_star*2)) .addColorStop({ '0.0': 'rgba(200,200,200,0.4)', '1.0': 'rgba(200,200,200,0)' })); var circl = new LC.Circle( x,y,r_star*0.8); //Рисуем круг ct.fill(circl, '#FFF');//Белый круг }else{ /* У тусклых звёздочек рисуем просто круг */ var circl = new LC.Circle( x,y,r_star); //Рисуем круг ct.fill(circl, '#FFF');//Белый круг } m++; } }
Планеты
Отображения на карте
Я решил выделить планеты жёлтым цветом ( подстраиваюсь под реальность). Для вычисления положений планет и написал библиотеку
Отображения в коллаже
Тут тоже пришлось немного поработать, и в итоге написал пару функций для отображения коллажа.
Так же внизу формировалась таблица с координатами планет.
Код отображения планет в головном файле:
//======================================Планеты====================================================================== for (var i = 0; i < (planets.length); i++){ var tyu=planetposition(planets[i][0], planets[i][1], jdn, planets[i][3], planets[i][4], planets[i][5], planets[i][6], planets[i][7], planets[i][8],planets[i][9],planets[i][10]) if (i==0){ sundelta=tyu[1] } if (planetinfo1==1){ //Формирование таблицы "инфо о планетах" res+="<tr><td>"+planets[i][8]+"</td><td>"+deltafloor(tyu[1])+"</td><td>"+alphafloor(tyu[0])+"</td><td>"+(tyu[3]).toFixed(3)+"</td><td>"+(tyu[2]).toFixed(1)+"</td><td>"+(2*tyu[4]).toFixed(1)+"</td></tr>"; } var zl=atmospheric_refraction(equatorial_to_horizontal(tyu[1], sr-15*tyu[0], phi)[1]);//Зенитное расстояние if (i==0){ sunz=zl } //alert(tyu) if (i>0){ draw(ctx, tyu[4], i,tyu[3],planets[i][8], date); } if (zl<90){ var Az=equatorial_to_horizontal(tyu[1], sr-15*tyu[0], phi)[0]; //Азимут var cor1=to_xy(zl,Az); var x=(cor1[0]*1).toFixed(0);//Абцисс координата var y=(cor1[1]*1).toFixed(0);//Ординат var R=Math.round((9-1*tyu[2])*kp2); if (R>10){ R=10 var R1=20*R if (planets[i][8]=='Солнце'){ //Делаем большой ореол для Солнца R=7 sunx=x suny=y } }else{ var R1=kp1*R } var circl = new LC.Circle( x,y,R); //Рисуем круг планеты var circl2 = new LC.Circle( x,y,R1); //Рисуем круг ореола ct.fill(circl, 'rgba('+planets[i][11][0]+','+planets[i][11][1]+','+planets[i][11][2]+',1)'); //заливаем круг планеты //пишем название планеты ct.text({ text: planets[i][8], padding: [ 1*y, 1*x], size:15, color:'rgba('+planets[i][11][0]+','+planets[i][11][1]+','+planets[i][11][2]+',1)' }); //alert(planets[i][11][0]) //Заливаем ореол градиентом----- ct.fill(circl2, ct .createRadialGradient( new LC.Circle(x, y, 1), new LC.Circle(x, y, R1)) .addColorStop({ '0.0': 'rgba('+planets[i][11][0]+','+planets[i][11][1]+','+planets[i][11][2]+',0.85)', '1.0': 'rgba('+planets[i][11][0]+','+planets[i][11][1]+','+planets[i][11][2]+',0)' }));/**/ //---------- } }
Луна
Я решил не мучатся, и не стал вырисовывать Луну вместе с фазой, потому что нагрузка и так высока.
Для отображения положения Луны брал готовый алгоритм Яна Мееуса, который нашёл на окраинах Интернета, поэтому решил его немного изменить и перепостить на :github
Кометы и астероиды
Здесь я до сих пор стою на перепутье, потому что сложно сказать насколько нужна эта функция: как правило кометы и астероиды слишком слабы для наблюдений. Поэтому я сделал только раздел для самых ярких комет. Собственно была написана библиотека вычисления положения кометы на параболической орбите: github
Проблемы и пути их решения
Главной проблемой является медлительность программы, особенно при быстром прокручивании. Тут сложно что-то сделать, наверное стоит алгоритмы урезать, но это моё мнение… На самом деле, я нечасто использую увеличение, поэтому этот баг редко ощущаю.
Находиться программа здесь:http://astrokot.ru/planetarium/dev/planetarium.html
ссылка на оригинал статьи http://habrahabr.ru/post/181554/
Добавить комментарий