Create a gist now

Instantly share code, notes, and snippets.

@wtnabe /MEMO
Created Sep 24, 2010

What would you like to do?
Geohash Visualizer 2, multiple geohashes can be drawn on google maps
1. rake fetch_lib
2. edit config.yaml ( skip OK )
3. rake open
geohash: xn3pvxy
zoom: 14
separator: ','
width: 500
height: 400
debug: false
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="geohash.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">google.load("jquery", "1.4");</script>
<title>Geohashエリア確認ツール2</title>
<style type="text/css" media="screen">
input[type="text"] {
width: 8em;
}
#map {
width: <%= config.width %>px;
height: <%= config.height %>px;
}
#address {
width: 20em;
}
#geohash {
width: 98%;
}
</style>
</head>
<body>
<div id="map"></div>
<form method="get" id="geocode">
<table>
<tr>
<th>Address</th>
<td><input id="address" type="text" name="address" value=""> <input type="submit" name="" value=" geocode ! " /></td>
</tr>
</table>
</form>
<form method="get" id="geoform">
<table>
<tr>
<th>Geohashes</th>
<td><textarea id="geohashes" type="text" name="geohashes" value=""><%= config.geohash4html %></textarea></td>
<td><input type="submit" name="" value=" geohash ! " /></td>
</tr>
</table>
</form>
<form method="get" id="mapinfo">
<table>
<tr>
<th>LatLng</th><th>Zoom</th><th>width</th><th>height</th>
</tr>
<tr>
<td><input id="latlng" type="text" name="latlng" value="" /></td>
<td><input id="zoom" type="text" name="zoom" value=""></td>
<td><input id="width" type="text" name="width" value="" /></td>
<td><input id="height" type="text" name="height" value="" /></td>
</tr>
<tr>
<td colspan="4" align="center"><input type="submit" name="" value=" 更新 ! " /></td>
</tr>
</table>
</form>
<script type="text/javascript" src="geohash_visualizer2.js"></script>
</body>
</html>
(function() {
var DEBUG = <%= config.debug %>;
/**
* Utilities for location.hash
*/
var Lh = {
SEPARATOR: '<%= config.separator %>',
DEFAULT_ZOOM_LEVEL: <%= config.zoom %>,
DEFAULT_GEOHASH: <%= config.geohash4js %>,
DEFAULT_WIDTH: '<%= config.width %>',
DEFAULT_HEIGHT: '<%= config.height %>',
/**
* right location hash string
*/
lh: function() {
return location.hash.substr( 1 );
},
/**
* extract geohash from location.hash
*
* @return string
*/
latlng: function () {
var latlng = this.lh().split( this.SEPARATOR )[0];
if ( !latlng ) {
latlng = $.isArray( this.DEFAULT_GEOHASH )
? this.DEFAULT_GEOHASH[0]
: this.DEFAULT_GEOHASH;
}
return latlng;
},
/**
* extract google maps' zoom level from location.hash
*
* @return int
*/
zoom: function() {
var zoom = this.lh().split( this.SEPARATOR )[1];
if ( !zoom ) {
zoom = this.DEFAULT_ZOOM_LEVEL;
}
return zoom - 0;
},
/**
* extract DOM width for google maps
*
* @return int
*/
width: function() {
var width = this.lh().split( this.SEPARATOR )[2];
if ( !width ) {
width = this.DEFAULT_WIDTH;
}
return width - 0;
},
/**
* extract DOM height for google maps
*
* @return int
*/
height: function() {
var height = this.lh().split( this.SEPARATOR )[3];
if ( !height ) {
height = this.DEFAULT_HEIGHT;
}
return height - 0;
},
/**
* @param string geohash
* @param int zoom
* @param int width
* @param int height
* @return string
*/
set: function( geohash, zoom, width, height ) {
var hash = [geohash, zoom, width, height].join( this.SEPARATOR );
location.hash = hash;
return hash;
}
};
/**
* Utilities for google.maps
*/
var Gmap = {
map: null,
mapid: 'map',
polygons: null,
geocoder: null,
width: null,
height: null,
/**
* convert from geohash to google.maps.LatLng array for google.maps.Polygon
*
* @param string geohash
* @return array
*/
square_path: function( geohash ) {
var l = decodeGeoHash( geohash );
var lats = l.latitude;
var lngs = l.longitude;
var square_routes = [[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]];
return jQuery( square_routes ).map( function( i, e ) {
return new google.maps.LatLng( lats[e[0]], lngs[e[1]] );
});
},
/**
* @return void
*/
draw_map: function() {
this.set_size( Lh.width(), Lh.height() );
var geohash = Lh.latlng();
var l = decodeGeoHash( geohash );
this.map = new google.maps.Map( document.getElementById( this.mapid ), {
center: new google.maps.LatLng( l.latitude[2], l.longitude[2] ),
mapTypeId: google.maps.MapTypeId.ROADMAP,
zoom: Lh.zoom()
});
this.draw_square();
},
/**
* @return void
*/
draw_square: function() {
if ( this.polygons ) {
this.erase_square();
}
var geohashes = Infobar.get( 'geohashes' );
if ( typeof geohashes != 'undefined' ) {
if ( !$.isArray( geohashes ) ) {
geohashes = [geohashes];
}
this.polygons = [];
self = this;
jQuery.each( geohashes, function( i, e ) {
var polygon = new google.maps.Polygon({
paths: self.square_path( e )
});
polygon.setMap( self.map );
self.polygons.push( polygon );
});
}
},
/**
* @return void
*/
erase_square: function() {
if ( $.isArray( this.polygons ) ) {
self = this;
jQuery.each( this.polygons, function( i, e ) {
e.setMap( null );
});
this.polygons = null;
}
},
/**
* @return int
*/
zoom: function() {
if ( this.map ) {
return this.map.zoom;
} else {
return Lh.zoom();
}
},
/**
* @since 2010-09-24
* @return int
*/
width: function() {
return $('#'+this.mapid).css( 'width' ).replace( /px$/, '' ) - 0;
},
/**
* @since 2010-09-24
* @return int
*/
height: function() {
return $('#'+this.mapid).css( 'height' ).replace( /px$/, '' ) - 0;
},
/**
* geohash for entire map
*
* @return string
* @bugs dummy
*/
geohash: function() {
if ( this.map ) {
var center = this.map.center;
return encodeGeoHash( center.b, center.c );
} else {
return Lh.latlng();
}
},
/**
* @param int width
* @param int height
*/
set_size: function( width, height ) {
$('#'+this.mapid).css( {width: width,
height: height} );
}
};
/**
* I/O for Information Bar in HTML
*/
var Infobar = {
get: function( id ) {
return ( id == 'geohashes' ) ? this._get_geohashes() : $('#' + id).val();
},
_get_geohashes: function() {
return $('#geohashes').val().split( /\r\n|[\r\n]/ );
},
set: function( id, val ) {
return ( id == 'geohashes' )
? this._set_geohashes( val )
: $('#'+id).val( val );
},
_set_geohashes: function( geohashes ) {
if ( !$.isArray( geohashes ) ) {
geohashes = [geohashes];
}
return $('#geohashes').val( geohashes.join( "\n" ) );
}
}
function dispatch() {
$('#'+Gmap.mapid).ready( function() {
Gmap.draw_map();
refresh_info();
google.maps.event.addListener( Gmap.map, 'zoom_changed', function() {
setTimeout( function() {
refresh_info();
}, 1500 );
});
google.maps.event.addListener( Gmap.map, 'center_changed', function() {
Infobar.set( 'latlng', Gmap.geohash() );
Lh.set( Gmap.geohash(), Gmap.zoom(), Gmap.width(), Gmap.height() );
});
});
jQuery( document ).ready( function( $ ) {
refresh_info();
/**
* Changer for location.hash and map from Infobar values
*/
$('#mapinfo').bind( 'submit', function( e ) {
Lh.set( Infobar.get( 'latlng' ),
Infobar.get( 'zoom' ),
Infobar.get( 'width' ),
Infobar.get( 'height' ) );
Gmap.draw_map();
return false;
});
$('#geocode').bind( 'submit', function( e ) {
set_addr( Infobar.get( 'address' ) );
return false;
});
$('#geoform').bind( 'submit', function( e ) {
Gmap.draw_square();
return false;
});
});
}
function refresh_info() {
Lh.set( Gmap.geohash(), Gmap.zoom(), Gmap.width(), Gmap.height() );
Infobar.set( 'latlng', Lh.latlng() );
Infobar.set( 'zoom', Gmap.zoom() );
Infobar.set( 'width', Gmap.width() );
Infobar.set( 'height', Gmap.height() );
}
function new_geohash() {
var len = Lh.latlng().length;
var geohash = encodeGeoHash( Gmap.map.center.b, Gmap.map.center.c );
return geohash.substr( 0, len );
}
function set_addr( address ) {
new google.maps.Geocoder().geocode({
address: address,
language: 'ja',
region: 'jp'
}, function( r, stat ) {
if ( stat == 'OK' ) {
var l = r[0].geometry.location;
var geohash = encodeGeoHash( l.b, l.c );
Lh.set( geohash, Gmap.zoom(), Gmap.width(), Gmap.height() );
Infobar.set( 'latlng', geohash );
Gmap.draw_map();
} else {
return false;
}
});
}
dispatch();
if ( DEBUG ) {
setTimeout( function() {
debugger;
}, 5000 );
}
})();
仕様
====
* 複数の geohash を google map 上に描画するツール
* 基準となる住所は human readable で与えることができる
* 住所を geocoding で encode して map の位置を変更できる
* textarea を parse できる
* textarea に 1行1つの geohash を入力できる
* 与えられた geohash をすべて google map 上に polygon で落とせる
* map の大きさを text で変更できる
* map を決定する緯度経度と zoom レベル、size を identifier として永続化できる
URI
===
#geohash,zoom,width,height
この geohash は map を決定するための geohash で map 上にレンダリングする geohash とはベツモノ
# -*- mode: ruby -*-
require 'yaml'
require 'erb'
require 'ostruct'
class Konfig < OpenStruct
def geohash4js
geohash = @table[:geohash]
case geohash
when String
return "'#{geohash}'"
when Array
return "['#{geohash.join( "','" )}']"
end
end
def geohash4html
geohash = @table[:geohash]
case geohash
when String
return geohash
when Array
return geohash.join( "\n" )
end
end
end
LIB = 'geohash.js'
DIST = FileList[['html','js'].map { |e| "geohash_visualizer2.#{e}.dist" }]
OBJ = FileList[['html','js'].map { |e| "geohash_visualizer2.#{e}" }]
CONFIG = File.dirname( __FILE__ ) + '/config.yaml'
desc "fetch latest geohash.js from github when geohash.js doesn't exist."
task :fetch_lib => LIB do
end
file LIB do
require 'open-uri'
LIB_LATEST = 'http://github.com/davetroy/geohash-js/raw/master/geohash.js'
open( LIB, 'wb' ) { |f|
f.puts URI( LIB_LATEST ).read
}
end
desc "create #{OBJ.join( ',' )}"
task :compile => OBJ do |t|
end
rule /\.(html|js)\z/ => [proc { |t| t + '.dist' }] << CONFIG do |t|
config = Konfig.new( YAML.load_file( CONFIG ) )
open( t.name, 'w' ) { |d|
open( t.source, 'r' ) { |o|
d.puts ERB.new( o.read ).result( binding )
puts "#{t.name} created."
}
}
end
desc 'open HTML'
task :open => OBJ do
sh 'open geohash_visualizer2.html'
end
task :default do
app = Rake.application
app.options.show_task_pattern = Regexp.new('')
app.display_tasks_and_comments
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment