むしゃくしゃしてやった

ぼーっとしてると、日曜日のこと思い出してうわーってなるので、余計なことを考えないようにプログラムの勉強してた。
http://jp.rubyist.net/magazine/?0019-cairoを参考にして(というか、ほとんどそのままだ)rcairo使ってruby白地図を描画するプログラム作ってみました。こういうことするとデータの力ってすごいなぁ、って思う。


ftpでファイルアップするのめんどいから、スーパーpre記法で掲載。

require 'cairo'

#海岸線データ
#
# http://rimmer.ngdc.noaa.gov/coast/から
# Coastline database:WVS and All Political Boundaries
# Coast Format options:Mapgen
# で取得
COAST_DATA_FILENAME = "coast.dat"

#出力画像ファイル名
OUTPUT_FILENAME = "whitemap.png"

#出力画像サイズ
OUTPUT_SIZE_WIDTH = 500
OUTPUT_SIZE_HEIGHT = 500

#経緯度クラス
class Point
	attr_accessor :lat, :lng
	
	def initialize(_lat,_lng)
		@lat = _lat
		@lng = _lng
	end
	
	def max(_point)
		@lat = [@lat,_point.lat].max
		@lng = [@lng,_point.lng].max
	end

	def min(_point)
		@lat = [@lat,_point.lat].min
		@lng = [@lng,_point.lng].min
	end
end

#海岸線データ読み込み
coastLines = Array.new

maxPoint = Point.new(-90,-180)
minPoint = Point.new(90,180)

File.open(COAST_DATA_FILENAME){|file|
	while line = file.gets
	line.chomp!
		if line == "# -b"
			points = Array.new
			coastLines << points
		else
			if valueFields = /(.+)\t(.+)/.match(line)
				coastPoint = Point.new(valueFields.captures[1].to_f,valueFields.captures[0].to_f)
				
				maxPoint.max(coastPoint)
				minPoint.min(coastPoint)

				points << coastPoint
				
			end
		end
	end
}

#地図描画用オブジェクト初期化
surface = Cairo::ImageSurface.new(Cairo::FORMAT_ARGB32, OUTPUT_SIZE_WIDTH, OUTPUT_SIZE_HEIGHT)
context = Cairo::Context.new(surface)

#背景塗りつぶし
context.set_source_rgb(1, 1, 1) # 白
context.rectangle(0, 0, OUTPUT_SIZE_WIDTH, OUTPUT_SIZE_HEIGHT)
context.fill

#経緯度に対するピクセルの割合を求める
ratio = [OUTPUT_SIZE_WIDTH / (maxPoint.lng - minPoint.lng),
OUTPUT_SIZE_HEIGHT / (maxPoint.lat - minPoint.lat)].min 

#海岸線描画
context.set_source_rgb(0, 0, 0) # 黒

coastLines.each {|drawLine|

	y = (maxPoint.lat - drawLine[0].lat) * ratio
	x = (drawLine[0].lng - minPoint.lng) * ratio
	context.move_to(x,y)
	
	drawLine.delete_at(0)
	drawLine.each{|drawPoint|
		y = (maxPoint.lat - drawPoint.lat) * ratio
		x = (drawPoint.lng - minPoint.lng) * ratio
		context.line_to(x,y)
    }
    context.stroke
}

#png形式で出力
surface.write_to_png(OUTPUT_FILENAME)

データはhttp://rimmer.ngdc.noaa.gov/coast/でMapgenっていう形式で取得しておくと。
rcairoは

Ruby-GNOME2 Project Website - Ruby-GNOME2 Project Website

Windows用インストールパッケージ入れたら入った。サーバサイドで動かせられれば、画像とかいじり放題ですね。なんか楽しそう。