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

в 14:50, , рубрики: canvas, javascript

Полгода назад решил написать 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

Автор: Lord_Katler_Bekket

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js