ITゲリラ戦士にアパッチはいらない Pt. 2 <TMSグリッドを表示するTMS サーバをつくるまで>
TMSのタイルファイル名を表示するTMSサーバを実装しました。
実装
タイル画像は RMagick で作ります。Rack には RMagick::Image#to_blob の出力を渡してあげるだけでOKです。
require 'stringio' require 'rubygems' require 'rmagick' use Rack::CommonLogger map '/' do run proc {|env| [200, {'Content-Type' => 'text/html'}, StringIO.new(<<-EOS <?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script src="http://openlayers.org/dev/OpenLayers.js"></script> <script> var map; function osm_getTileURL(bounds) { var res = this.map.getResolution(); var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w)); var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h)); var z = this.map.getZoom(); var limit = Math.pow(2, z); if (y < 0 || y >= limit) { return OpenLayers.Util.getImagesLocation() + "404.png"; } else { x = ((x % limit) + limit) % limit; return this.url + z + "/" + x + "/" + y + "." + this.type; } } function init() { map = new OpenLayers.Map('map', { controls:[ new OpenLayers.Control.Navigation(), new OpenLayers.Control.PanZoomBar(), new OpenLayers.Control.LayerSwitcher(), new OpenLayers.Control.Permalink(), new OpenLayers.Control.MousePosition(), new OpenLayers.Control.Attribution()], maxExtent: new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34), numZoomLevels:18, maxResolution: 156543.0399, units: 'm', projection: new OpenLayers.Projection("EPSG:900913"), displayProjection: new OpenLayers.Projection("EPSG:4326")}); var tah = new OpenLayers.Layer.TMS( 'OSM Tiles@Home', 'http://tah.openstreetmap.org/Tiles/tile/', {type: 'png', getURL: osm_getTileURL, displayOutsideMaxExtent: true, attribution: 'map: OpenStreetMap Tiles@Home'}); var ltm = new OpenLayers.Layer.TMS( 'TMS Grid by TMS', 'http://' + window.location.host + '/tms/', {type: 'png', getURL: osm_getTileURL, displayOutsideMaxExtent: true, isBaseLayer: false, attribution: 'Local TMS'}); map.addLayers([ltm, tah]); if(!map.getCenter()) { map.setCenter(new OpenLayers.LonLat(9.69873, 52.38736).transform( new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")), 15); } } </script> </head> <body onload="init()"> <div id="map"></div> </body> </html> EOS )] } end map '/tms' do run proc {|env| img = Magick::Image.new(256, 256) { self.format = 'PNG' } img.opacity = 65535 draw = Magick::Draw.new draw.pointsize = 16 draw.gravity = Magick::CenterGravity draw.annotate(img, 0, 0, 2, 2, env['PATH_INFO']) draw.stroke('gray') draw.stroke_width = 1 draw.fill_opacity(0) draw.stroke_opacity(0.5) draw.polyline(0, 0, 255, 0, 255, 255, 0, 255, 0, 0) draw.draw(img) [200, {'Content-Type' => 'image/png'}, img.to_blob] } end