LibCanvas: На пути к звёздам

от автора

Полгода назад решил написать online-приложение карту звёздного неба. Думаю, многие из нас когда-либо видели эту самую карту звёздного неба, и вероятно, она привлекала к себе внимание.
Я подумал, что интересно будет осуществить нечто подобное на JS. Было решено отчасти использовать готовую библиотеку LibCanvas из-за её продуманного синтаксиса, что было важно при написании объёмных приложений.
image


Первая проблема, с которой я столкнулся — это довольно большое количество звёзд, которое требуется отобразить с высокой точностью — их около 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *