SVGで星図を描こう
人生に一度くらいは、「急に満天の星空を描かなければならなくなった!」という事態が発生すると思います。
手描きするのもなんですので、ここはひとつ簡単に描いてみましょう。
※こんな出だしですが、これはベクター画像フォーマットSVGとたわむれる記事です。
1. 星のデータをもらってくる
他の星図を見ながら手描きで星をひとつひとつ打っていくのは面倒ですね。
なので最初から座標が入っているデータをもらってきます。
CSVを見てみると、このへんに天球座標が入っています(RA=赤経、Dec=赤緯)
2. データを処理する
CSVに載っている星の数を確認したら、87475個ありました。さすがにそんなに描画すると画像の重さが心配になってくるので、ダイエットさせようと思います。
今回は暫定的に6等星まで(6.5等星より明るい星)を載せることにしますので、Mag(等級)の列でそれ未満の星のデータを削除します。
これはExcelでやりました。簡単ですね。
星の数は8852個になりました。
3. SVGを書き出すスクリプトを作る
タイトルからSVGを連呼しておりましたが、この画像形式は正式にはScalable Vector Graphicsと申しまして、中身は我々に馴染み深いXMLです。
XMLということはテキスト→テキストを吐き出すだけでベクター画像が作れてしまうんですって!→お手軽!
では、やってみましょう。
※Perlは仕事の効率化程度にしか使ってないので、稚拙さについては一旦スルーいただければ幸いです。
#! /usr/bin/perl -w # ライブラリとか use strict; use utf8; use warnings; use Text::CSV::Simple; use IO::File; use Fcntl qw(:flock); use Math::Round; # 変数とか my $csv_path = 'C:\path\stardata_65.csv'; my $svg_path = 'C:\path\starmap.svg'; my $paper_width = 3600; #描画幅 my $paper_height = $paper_width / 2; #描画高 my $equator = $paper_height / 2; #紙の上での赤道 my $plot = ''; my $i = 0; # ガイド的に赤緯赤経の線を引いておく for($i=0; $i<37; $i++){ my $lx = ($paper_width / 36) * $i; $plot .= ''."\n"; } for($i=0; $i<19; $i++){ my $ly = ($paper_height / 18) * $i; $plot .= ''."\n"; } # CSV読み込み my $parser = Text::CSV::Simple->new({binary => 1}); $parser->want_fields(6, 7, 8, 10); #名前・赤緯・赤経・等級 $parser->field_map(qw/PN RA Dec Mag/); my @csv = $parser->read_file($csv_path); # 1行ずつ座標変換処理を行う for($i=0; $i<=$#csv; $i++){ my $pn = $csv[$i]->{'PN'}; #名前 my $cx = $paper_width - ($csv[$i]->{'RA'} * 15 * ($paper_width / 360)); #赤緯 my $cy = $paper_height - ($csv[$i]->{'Dec'} * ($equator / 90) + $equator); #赤経 my $mag = round($csv[$i]->{'Mag'}); #等級(四捨五入) # 視等級によって見た目を変える if($mag < 1) { #0等星以上 $plot .= ''."\n"; } elsif($mag == 1) { #1等星 $plot .= ''."\n"; } elsif($mag == 2) { #2等星 $plot .= ''."\n"; } elsif($mag == 3) { #3等星 $plot .= ''."\n"; } elsif($mag == 4) { #4等星 $plot .= ''."\n"; } elsif($mag == 5) { #5等星 $plot .= ''."\n"; } else { #6等星 $plot .= ''."\n"; } # 名前が空欄でなかったら星と同じ座標に配置 if(length($pn) > 0) { $plot .= ''."\n"; $plot .= ''.$pn.''."\n"; $plot .= ''."\n"; } } $plot = ''; # SVG書き出し my $io = IO::File->new($svg_path, 'w'); flock($io, LOCK_EX); $io->print($plot); flock($io, LOCK_UN); $io->close; exit;
4. 実行する
できたスクリプトを実行するとstarmap.svgが生成されますので、ビューアで見てみましょう。
できたー! 見慣れた星の並びが再現されています。
5. Illustratorで処理する
星がカラフルすぎるので、もうちょっと星図らしくしましょう。
Illustratorで開いて「選択」→「共通」→アピアランスなどで星の等級別などにレイヤー分けしておきます。
せっかくだからかわいくしたいので、シンボルを作ってみました。
これを丸の画像と差し替えていきます。
シンボルに置き換えて、「オブジェクト」→「変形」→「個別に変形」でランダムに回転させます。
だいぶ星図っぽくなってきました。
6. 星座線を足す
ここまではスクリプトと一括処理を駆使してまいりましたが、仕上げは少し手をかけてみましょう。
Wikipediaなどと見比べながら、星座線を足してみます。
最初のデータにどの星と星をつなぐかのデータも入っていれば自動化できたのですが……。
※簡単に書いてますが最大の地獄なので、赤経赤緯の線をガイドに頑張りましょう。
ここでは以前に描いたものを適当にコピーしてきました。
かなりそれっぽくなりました。
この時に星座名と足りてない星の名前も入れてしまいます。
重なってる星は適宜ずらして重星らしくしてみたりもします。
全然関係ありませんが、星座線を引いていて、オリオン座って着痩せするタイプなんだと思いました。
7. 完成!
赤経赤緯の線を非表示にして、できました!
今回は簡単なので正距円筒図法で作成しましたが、プロット方法を変えれば好きな図法で描けますので色々お試しください。
好きな色にして印刷して使ってもいいですね。
8. まとめ
SVGはブラウザで表示できるベクター画像というところに注目されがちですが、画像作成の下ごしらえとしてもご活用いただけるかと思いますので、是非ご検討ください。
どうぞよろしくお願いいたします。