この記事は5年以上前の情報で、内容が古くなっている可能性があります。

Illustratorで星図と星座を描くスクリプト

star_map_sample

星座の豆本を作りたいということで、星座のイラレのデータが落ちてないかなーっと探していたのですが、自由に使っていいよーって感じのが見つからなかったので自分で作ってみました。
ちなみにWin版CS5でしか動作確認していないので、他のバージョンで動くかは不明です。

星と星座に関する知識はてきとうにググったり星の図鑑みたいなの読んで調べときましょう。

星と星座にかかわるデータを探してくる

Astro Commonsというサイトから、星の位置・星の名前・星座の位置・星座線・星座境界線のデータをダウンロードしてきました。

星図関連のデータ探してると度々出てくる「星座横丁」というサイトをリニューアルされたものです。

星図・星座境界線のデータは探すといろいろ出てきます。

星座線のデータについては探し方がイマイチだったのか、Astro Commons以外では見つかりませんでした。

座標を変換する

星の位置は、赤緯・赤経で定義されているのですが、表す単位がそれぞれ違います。

赤緯:度数表記
値の範囲:-90度(天の南極点)~0度(天の赤道)~90度(天の北極点)
度数未満の単位は、分・秒
赤経:時・分表記
値の範囲:0時~24時
時未満の単位は、分・秒

単位を統一しないとやりにくいので統一します。赤経を360度の単位に変換します。

赤経の1時間は15度。1分は0.25度。1秒ははぶいても大差なさそうなのではぶきました。

変換処理に使ったツールはAccessのVBA。お手軽なので。Excelでも地道にやればいけるかと。テキストが処理できればPerlでもPHPでもなんでもいけるのでお好みのものを使えばいいかと。

座標変換について参考にしたサイトは下記

座標のデータを読み込んで描画する

座標を変換して、必要なものだけ出力したのが下記データ(タブ区切りテキスト)。※星は視等級が6以下のものを対象

星の位置と星の名前(5044件):star_map.txt
HIP / 赤経 / 赤緯 / 視等級 / 星の名前
星座の名前(88件):constellation.txt
星座ID / 赤経 / 赤緯 / 学名 / 日本語名
星座線(673件):constellation_line.txt
星座ID / 赤経始点 / 赤緯始点 / 赤経終点 / 赤緯終点
星座境界線(1582件):constellation_boundary.txt
星座ID / 赤経始点 / 赤緯始点 / 赤経終点 / 赤緯終点

スクリプトは下記3種類。
それぞれアクティブなドキュメントに描画されます。動作条件がいろいろあるので、そこはソースを読んでください。

星の位置と星の名前を描画するスクリプト

//星図と恒星の名前を描画する
//下記の段落スタイルとシンボルが現在アクティブなドキュメントにあること前提で動く

var DEG2RAD = Math.PI / 180;  //度数からラジアンに変換

var ZOOM = 10;  //座標を何倍にするか

//描画範囲と描画方法
var MAP_TYPE = 0;  //0=全天(赤緯-60~60の範囲のみ) メルカトル図法 / 1=北天 正距方位図法 / 2=南天 正距方位図法

//星図のファイルパス
var filepath_starmap = "star_map.txt";

//星のシンボル名 等級毎に定義しておく
var symbol_star = [];
symbol_star[0] = "grade_0A";  //等級 0.5未満
symbol_star[1] = "grade_0B";  //等級 0.5~1未満
symbol_star[2] = "grade_1A";  //等級 1~1.5未満
symbol_star[3] = "grade_1B";  //等級 1.5~2未満
symbol_star[4] = "grade_2";   //等級 2
symbol_star[5] = "grade_3";   //等級 3
symbol_star[6] = "grade_4";   //等級 4
symbol_star[7] = "grade_5";   //等級 5
symbol_star[8] = "grade_6";   //等級 6

//星の名前の段落スタイル名
var paragraph_style_star_name = "star_name";

//現在アクティブなドキュメント
var doc = app.activeDocument;

//星のデータ
var stars = [];

main();

function main(){
  
  //ファイルからデータ設定
  setStarData(filepath_starmap);
  
  //星図を描画
  drawStarMap();
  
  alert("end");
}


//星図を描画する
function drawStarMap(){
  
  var stars_layer = doc.layers.add();
  stars_layer.name = "star_map";

  var star_names_layer = doc.layers.add();
  star_names_layer.name = "star_name";

  var star_num = stars.length;

  for(var i=0; i<star_num; i++) {
    
    var star = stars.pop();
    
    var symbol_name = symbol_star[star.grade_index];
      
    var target_symbol = doc.symbols.getByName(symbol_name);	 
    var star_item = stars_layer.symbolItems.add(target_symbol);

    star_item.left = star.x - star_item.width / 2;
    star_item.top = star.y + star_item.width / 2;	
    
    star_item.name = star.hip;
    
    //星の名前	
    var para_style = doc.paragraphStyles.getByName(paragraph_style_star_name);
    
    drawText(star.x, star.y, star.proper, star_names_layer, para_style);
  }
}


//星のデータをまとめとく
function Star(hip, ra, dec , vmag, proper){
    
  this.hip = hip;
  this.proper = proper;	
  this.vmag = vmag;

  var pos = new Position(ra, dec);
  this.x = pos.x;
  this.y = pos.y;
  
  if(isNaN(vmag)){
    vmag = 0;
  }
  
  var grade = Math.floor(vmag);
  
  if(grade < 0){
    grade_index = 0;
  }
  else if(grade > 6){
    grade_index = 6;
  }
  
  if(grade == 0){
    if(vmag < 0.5){
      grade_index = 0
    }
    else{
      grade_index = 1
    }
  }else if(grade == 1){
    if(vmag < 1.5){
      grade_index = 2
    }
    else{
      grade_index = 3
    }
  }
  else{
    grade_index = grade + 2;
  }

  this.grade_index = grade_index;
}


//星のデータをファイルから読み込む
function setStarData(path){
        
  var file = new File(path);
    
  if(file.open("r")){
        
    var row = 0;
    
    while(! file.eof){			
                      
      var line = file.readln();

      if(line.length > 0){

        var item = line.split("\t");

        var hip = item[0];

        //赤経(X)
        var  ra = item[1];
        
        //赤緯(Y)
        var dec = item[2];

        //視等級
        var vmag = item[3];
                
        //星の名前
        var proper = item[4];

        if((MAP_TYPE == 0  && dec >= -60 && dec <= 60)||  (MAP_TYPE == 1 && dec >= 0) || (MAP_TYPE == 2 && dec <= 0)){
          var star = new Star(hip, ra, dec , vmag, proper);
          stars.push(star);
        }				
      }
    }
  }
  else{     
    alert("file open error: " + path);
  }
}


//赤経赤緯をXY座標に変換
function Position(ra, dec){

  this.x = 0;
  this.y = 0;
  
  if(MAP_TYPE == 0){
    
    this.x = -ra * ZOOM;
    this.y = dec * ZOOM;
  }
  else if(MAP_TYPE == 1){					
    
    this.x = - Math.cos((ra - 270) * DEG2RAD) * (90 - dec) * ZOOM;
    this.y  = Math.sin((ra - 270) * DEG2RAD) * (90 - dec)  * ZOOM;
  }
  else if(MAP_TYPE == 2){
    
    this.x = Math.cos((ra - 270) * DEG2RAD) * (-90 - dec) * ZOOM;
    this.y = Math.sin((ra - 270) * DEG2RAD) * (-90 - dec)* ZOOM;		
  }
}


//文字を描画する
function drawText(x, y, contents, layer, pstyle){
  
  if(! contents){
    return;
  }

  var txtfrm= layer.textFrames.add();
  
  txtfrm.contents = contents;
  txtfrm.left = x;
  txtfrm.top = y;
  
  var paras = txtfrm.paragraphs;
  var para_len = paras.length;
  for(var p = 0; p<para_len; p++){
    var para = paras[p];
    pstyle.applyTo(para, true);
  }
}

星座名と星座線と星座境界線を描画するスクリプト

//星座と星座名と星座境界線を描く
//下記の段落スタイルとスウォッチが現在アクティブなドキュメントにあること前提で動く

var DEG2RAD = Math.PI / 180;  //度数からラジアンに変換

var ZOOM = 10;  //座標を何倍にするか

//描画範囲と描画方法
var MAP_TYPE = 0;  //0=全天(赤緯-60~60の範囲のみ) メルカトル図法 / 1=北天 正距方位図法 / 2=南天 正距方位図法 ※正距方位図法はざっくり適当のため、線分は直線で描画

var paragraph_style_constllation_name = "constllation_name"; //星座名の段落スタイル名
var swatche_constllation_line = "constllation_line"; //星座線色のスウォッチ名
var swatche_constllation_boundary = "boundary_line" //星座境界線色のスウォッチ名

//星座のファイルパス
var filepath_constllation_name = "constellation.txt"; 

//星座線のファイルパス
var filepath_constllation_line = "constellation_line.txt";

//星座境界線のファイルパス
var filepath_constllation_boundary = "constellation_boundary.txt";

//現在アクティブなドキュメント
var doc = app.activeDocument;

main();

function main(){
  //星座名
  //drawConstllationName();

  //星座線
  drawConstllationLine();

  //星座境界線
  //drawConstllationBoundary();
  
  alert("end");
}


//星座名を描画する
function drawConstllationName(){
  
  var const_layer_en = doc.layers.add();
  const_layer_en.name = "constllation_name_en";
  
  var const_layer_ja = doc.layers.add();
  const_layer_ja.name = "constllation_name_ja";
  
  var file = new File(filepath_constllation_name);
    
  if(file.open("r")){
        
    var row = 0;
    
    while(! file.eof){			
                      
      var line = file.readln();

      if(line.length > 0){

        var item = line.split("\t");

        var id = item[0];

        //赤経(X)
        var  ra = item[1];
        
        //赤緯(Y)
        var dec = item[2];

        //学名(英語)
        var name_en = item[3];
                
        //日本語名
        var name_ja = item[4];
        
        var pos = new Position(ra, dec);
      
        var para_style = doc.paragraphStyles.getByName(paragraph_style_constllation_name);	 

        if((MAP_TYPE == 0  && dec >= -60 && dec <= 60)||  (MAP_TYPE == 1 && dec >= 0) || (MAP_TYPE == 2 && dec <= 0) ){
          
          drawText(pos.x, pos.y, name_en, const_layer_en, para_style);
          drawText(pos.x, pos.y, name_ja, const_layer_ja, para_style);
        }
      }
    }
  }
  else{     
    alert("file open error: " + path);
  }	
}


//星座線を描画する
function drawConstllationLine(){
  
  var line_layer = doc.layers.add();
  line_layer.name = "constllation_line";
  
  var line_swatch = doc.swatches.getByName(swatche_constllation_line);
  var line_color = line_swatch.color;
  
  var line_width = 1; // point
  
  var file = new File(filepath_constllation_line);
    
  if(file.open("r")){
        
    var row = 0;
    
    while(! file.eof){			
                      
      var line = file.readln();

      if(line.length > 0){

        var item = line.split("\t");

        var id = item[0];

        //赤経始点
        var  ra_start = item[1];
        
        //赤緯始点
        var dec_start = item[2];
        
        //赤経終点
        var  ra_end = item[3];
        
        //赤緯終点
        var dec_end = item[4];
        
        if(Math.abs(ra_start - ra_end) < 180){
        
          var pos_start = new Position(ra_start, dec_start);
          var pos_end =  new Position(ra_end, dec_end);
          
          if((MAP_TYPE == 0  && dec_start >= -60 && dec_start <= 60) ||  (MAP_TYPE == 1 && dec_start >= 0) || (MAP_TYPE == 2 && dec_start <= 0) ){

            drawLine(pos_start.x, pos_start.y, pos_end.x, pos_end.y, line_layer, line_color, line_width);
          }
        }
      }
    }
  }
  else{     
    $.writeln("file open error: " + path);
  }
}


//星座境界線を描画する
function drawConstllationBoundary(){
  
  var line_layer = doc.layers.add();
  line_layer.name = "boundary_line";
  
  var line_swatch = doc.swatches.getByName(swatche_constllation_boundary);
  var line_color = line_swatch.color;
  
  var line_width = 1; // point
  
  var file = new File(filepath_constllation_boundary);
    
  if(file.open("r")){
        
    var row = 0;
    
    while(! file.eof){			
                      
      var line = file.readln();

      if(line.length > 0){

        var item = line.split("\t");

        var id = item[0];

        //赤経始点(X)
        var  ra_start = item[1];
        
        //赤緯始点(Y)
        var dec_start = item[2];
        
        //赤経終点(X)
        var  ra_end = item[3];
        
        //赤緯終点(Y)
        var dec_end = item[4];

        var pos_start = new Position(ra_start, dec_start);
        var pos_end =  new Position(ra_end, dec_end);
        
        if((MAP_TYPE == 0  && dec_start >= -60 && dec_start <= 60) ||  (MAP_TYPE == 1 && dec_start >= 0) || (MAP_TYPE == 2 && dec_start <= 0)){
          drawLine(pos_start.x, pos_start.y, pos_end.x, pos_end.y, line_layer, line_color, line_width);
        }
      }
    }
  }
  else{     
    $.writeln("file open error: " + path);
  }
}


//赤経赤緯をXY座標に変換
function Position(ra, dec){

  this.x = 0;
  this.y = 0;
  
  if(MAP_TYPE == 0){
    
    this.x = -ra * ZOOM;
    this.y = dec * ZOOM;
  }
  else if(MAP_TYPE == 1){					
    
    this.x = - Math.cos((ra - 270) * DEG2RAD) * (90 - dec) * ZOOM;
    this.y  = Math.sin((ra - 270) * DEG2RAD) * (90 - dec)  * ZOOM;
  }
  else if(MAP_TYPE == 2){
    
    this.x = Math.cos((ra - 270) * DEG2RAD) * (-90 - dec) * ZOOM;
    this.y = Math.sin((ra - 270)  * DEG2RAD) * (-90 - dec)* ZOOM;		
  }
}


//線を描画する
function drawLine(x1, y1, x2, y2, layer, color, width){
  
  var line = layer.pathItems.add();
  
  line.stroked = true;
  line.strokeColor = color;	
  line.strokeWidth = width; //point
  
  line.filled = false;
  
  line.setEntirePath( Array ( Array(x1, y1), Array(x2, y2) ) );	
}


//文字を描画する
function drawText(x, y, contents, layer, pstyle){
  
  if(! contents){
    return;
  }

  var txtfrm= layer.textFrames.add();
  
  txtfrm.contents = contents;
  txtfrm.left = x;
  txtfrm.top = y;
  
  var paras = txtfrm.paragraphs;
  var para_len = paras.length;
  for(var p = 0; p<para_len; p++){
    var para = paras[p];
    pstyle.applyTo(para, true);
  }
}

グリッド線を描画するスクリプト

//星図の赤経赤緯のグリッドを描く
//下記のスウォッチが現在アクティブなドキュメントにあること前提で動く

var DEG2RAD = Math.PI / 180;  //度数からラジアンに変換

var ZOOM = 10;  //座標を何倍にするか

var MAP_TYPE = 0;  //描画方法 0=全天(赤緯-60~60の範囲のみ) メルカトル図法 / 1=北天 正距方位図法 / 2=南天 正距方位図法  ※1と2は描画同じ 他のスクリプトと合わせる為に設定

var swatche_grid_line = "starmap_grid"; //グリッド線色のスウォッチ名

var doc = app.activeDocument;

main();

function main(){
  
  if(MAP_TYPE == 0){
    drawGrid();
  }
  else {
    drawGrid2();
  }

  alert("end");
}

//メルカトル図法(直交)グリッド線を描く
function drawGrid(){
  
  var line_layer = doc.layers.add();
  line_layer.name = "starmap_grid";
  
  var line_swatch = doc.swatches.getByName(swatche_grid_line);
  var line_color = line_swatch.color;
  
  var line_width = 1; //point
  
  var step = 10 * ZOOM;
  
  var line_x_start = 0;
  var line_x_end = -36 * step;
  var line_y_start = -6 * step;
  var line_y_end = 6 * step;
  
  //赤経(0 ~ 360)
  for(var x=0; x <= 36; x++){
    
    drawLine(-x * step, line_y_start, -x * step,  line_y_end, line_layer, line_color, line_width);
  }
  
  //赤緯1(-60~0)
  for(var y=0; y <= 6; y++){
    
    drawLine(line_x_start, y * step, line_x_end, y * step, line_layer, line_color, line_width);
  }
  
  //赤緯2(0~60)
  for(var y=0; y <= 6; y++){
    
    drawLine(line_x_start, -y * step, line_x_end, -y * step, line_layer, line_color, line_width);
  }

}

//正距方位図法(円形に広がる)グリッド線を描く
function drawGrid2(){

  var line_layer = doc.layers.add();
  line_layer.name = "starmap_grid";
  
  var line_swatch = doc.swatches.getByName(swatche_grid_line);
  var line_color = line_swatch.color;
  
  var line_width = 1; //point
  
  var step = 10;
  
  //赤経
  for(var r=0; r <= 9; r++){
    
    drawCircle(0, 0, r * step * ZOOM, line_layer, line_color, line_width);
  }
  
  //赤緯
  for(var r=0; r < 36; r++){
    
    var x = Math.cos(r * 10  * DEG2RAD) * 9 * step * ZOOM;
    var y = Math.sin(r  * 10 * DEG2RAD)  * 9 * step * ZOOM;
    
    drawLine(0, 0, x, y, line_layer, line_color, line_width);
  }
}


function drawLine(x1, y1, x2, y2, layer, color, line_width){
  
  var item = layer.pathItems.add();
  
  item.stroked = true;
  item.strokeColor = color;	
  item.strokeWidth = line_width;
  
  item.filled = false;
  
  item.setEntirePath( Array ( Array(x1, y1), Array(x2, y2) ) );	
}


function drawCircle(x, y, r, layer, color, line_width){
  
  var top = y + r;
  var left = x - r;
  var width = r * 2
  var height = r * 2;
  
  var item =layer.pathItems.ellipse(top, left,  width,  height, false, true);
  
  item.stroked = true;
  item.filled = false;
  item.strokeColor = color;	
  item.strokeWidth = line_width;
}

下記のように描画されます。※背景の黒い図形は描画されません。

  • 中緯度(赤緯:-60度~60度):
    star_map
  • 北天(赤緯:0度~90度):
    star_map_north
  • 南天(赤緯:-90度~0度):
    star_map_south

思いっきりアートボード外に描画されますが、そのまま使うわけではないので、適当に移動しましょう。

スクリプトの設定してある定数を変えると、北天と南天の描画もできます。
データファイルの位置とかシンボル名とか変えたいときはスクリプト書き換えてください。
(データファイルが存在しない場合のみエラーが出ますが、シンボル・スウォッチがない場合は実行時エラーで止まります)

星は全てシンボルにしてあります。星図・星座線・星座名などは全てレイヤー分けされます。色は全部スウォッチに入ってます。
シンボルや色を適当に変更するとそれっぽいものができるかと。

ちなみに星座線は特にきまりがないらしいので、本に載ってるの星座表とかと違うかもしれません。
本に載ってるのに合わせたいなーっと思いましたら、手動で線を引くなり座標データを入力して作り直すなりして変更しましょう。

出来上がったAIファイルとスクリプトは自由に使用・改変OKです。
使用した際の責任は負えませんので承知の上でご使用下さい。(星座が間違っててクレームが!とかなっても知りませんので…。)