琵琶湖をPostScriptで描く
先日の日曜日、自転車で琵琶湖をまわってきました。
今年はAndroid端末 HTC DesireでMy Tracksというソフトを動かし、
GPSのログを記録しながら走ってみました。
で、せっかくなの、でそのログを使ってPostScriptで琵琶湖を描いてみました。
PDF
PostScript
なかなかいい感じに出来ました。
滋賀県民以外なら「これが琵琶湖の正確な形です」といっても騙せそうです。
(滋賀県民には「奥琵琶湖の形がおかしい」などとツッコまれそうだ。)
MyTracksは緯度経度のログをCSV形式で、出力することができるので、
それをCommon Lispで読み込み、PostScriptに変換という流れで作りました。
変換につかったプログラムは以下のとおりです。
(defun skip-elms (stream n) (when (char= (peek-char nil stream) #\,) (read-char stream)) (dotimes (i n) (unless (char= (peek-char nil stream) #\,) (read stream)) (assert (char= (read-char stream) #\,)))) (defun read-latlon (line) (let (lat lon) (with-input-from-string (s line) (skip-elms s 2) (setf lat (read-from-string (read s))) (skip-elms s 0) (setf lon (read-from-string (read s)))) (values lat lon))) (defun convert-latlon (lat lon) (values (+ 50 (* (- (* lat 111) 3881) 11)) (+ 50 (* (- (* lon 91) 12363) 11)))) (defun doit () (with-open-file (s "biwa.csv") (with-open-file (out "biwa01.ps" :direction :output :if-exists :supersede) (write-line "%!" out) (write-line "gsave" out) (dotimes (_ 3611) (read-line s)) (do ((i 3612 (1+ i))) ((>= i 30334) t) (multiple-value-bind (lat lon) (multiple-value-call #'convert-latlon (read-latlon (read-line s))) (if (= i 3612) (format out "~A ~A moveto~%" lon lat) (format out "~A ~A lineto~%" lon lat)))) (format out "stroke~%showpage~%grestore"))))
マジックナンバーがたくさん出てますが、
書き捨てのプログラムなので気にしない方針で。
convert-latlonは緯度経度をPostScriptの座標(ポイント)に変換します。
数111は緯度1度あたりのおおよその距離(km)、
数91は経度1度あたりのおおよその距離(km)、
あとの数はA4用紙全体を使うように調整するためのものです。
かなり大雑把ですが、それなりに見栄えがいいのでいいことにしてください。
おまけ: