<s> import xml . sax <EOL> import copy <EOL> from math import * <EOL> from graphserver . vincenty import vincenty <EOL> INFINITY = float ( '<STR_LIT>' ) <EOL> def download_osm ( left , bottom , right , top ) : <EOL> """<STR_LIT>""" <EOL> from urllib . request import urlopen <EOL> fp = urlopen ( "<STR_LIT>" % ( left , bottom , right , top ) ) <EOL> return fp <EOL> def dist ( x1 , y1 , x2 , y2 ) : <EOL> return ( ( x2 - x1 ) ** <NUM_LIT:2> + ( y2 - y1 ) ** <NUM_LIT:2> ) ** <NUM_LIT:0.5> <EOL> def dist_haversine ( x0 , y0 , x1 , y1 ) : <EOL> radius = <NUM_LIT> <EOL> lon0 = x0 * PI / <NUM_LIT> <EOL> lat0 = y0 * PI / <NUM_LIT> <EOL> lon1 = x1 * PI / <NUM_LIT> <EOL> lat1 = y1 * PI / <NUM_LIT> <EOL> dLat = ( lat1 - lat0 ) <EOL> dLon = ( lon1 - lon0 ) <EOL> a = sin ( dLat / <NUM_LIT:2> ) * sin ( dLat / <NUM_LIT:2> ) + cos ( lat0 ) * cos ( lat1 ) * sin ( dLon / <NUM_LIT:2> ) * sin ( dLon / <NUM_LIT:2> ) <EOL> c = <NUM_LIT:2> * atan2 ( sqrt ( a ) , sqrt ( <NUM_LIT:1> - a ) ) <EOL> return radius * c <EOL> class Node : <EOL> def __init__ ( self , id , lon , lat ) : <EOL> self . id = id <EOL> self . lon = lon <EOL> self . lat = lat <EOL> self . tags = { } <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . id , self . lon , self . lat , len ( self . tags ) ) <EOL> class Way : <EOL> def __init__ ( self , id , osm , tolerant = False ) : <EOL> self . osm = osm <EOL> self . id = id <EOL> self . nd_ids = [ ] <EOL> self . tags = { } <EOL> self . tolerant = tolerant <EOL> @ property <EOL> def nds ( self ) : <EOL> for nd_id in self . nd_ids : <EOL> try : <EOL> yield self . osm . nodes [ nd_id ] <EOL> except KeyError : <EOL> if self . tolerant : <EOL> pass <EOL> else : <EOL> raise KeyError ( "<STR_LIT>" % nd_id ) <EOL> @ property <EOL> def geom ( self ) : <EOL> return [ ( nd . lon , nd . lat ) for nd in self . nds ] <EOL> @ property <EOL> def bbox ( self ) : <EOL> l = INFINITY <EOL> b = INFINITY <EOL> r = - INFINITY <EOL> t = - INFINITY <EOL> for x , y in self . geom : <EOL> l = min ( l , x ) <EOL> r = max ( r , x ) <EOL> b = min ( b , y ) <EOL> t = max ( t , y ) <EOL> return ( l , b , r , t ) <EOL> def split ( self , dividers ) : <EOL> def slice_array ( ar , dividers ) : <EOL> for i in range ( <NUM_LIT:1> , len ( ar ) - <NUM_LIT:1> ) : <EOL> if dividers [ ar [ i ] ] > <NUM_LIT:1> : <EOL> left = ar [ : i + <NUM_LIT:1> ] <EOL> right = ar [ i : ] <EOL> rightsliced = slice_array ( right , dividers ) <EOL> return [ left ] + rightsliced <EOL> return [ ar ] <EOL> slices = slice_array ( self . nd_ids , dividers ) <EOL> ret = [ ] <EOL> i = <NUM_LIT:0> <EOL> for slice in slices : <EOL> littleway = copy . copy ( self ) <EOL> littleway . id += "<STR_LIT>" % i <EOL> littleway . nd_ids = slice <EOL> ret . append ( littleway ) <EOL> i += <NUM_LIT:1> <EOL> return ret <EOL> def get_projected_points ( self , reprojection_func = lambda x , y : ( x , y ) ) : <EOL> """<STR_LIT>""" <EOL> ret = [ ] <EOL> for nodeid in self . nd_ids : <EOL> node = self . osm . nodes [ nodeid ] <EOL> ret . append ( reprojection_func ( node . lon , node . lat ) ) <EOL> return ret <EOL> def to_canonical ( self , srid , reprojection_func = None ) : <EOL> """<STR_LIT>""" <EOL> return "<STR_LIT>" % ( srid , "<STR_LIT:U+002C>" . join ( [ "<STR_LIT>" % ( x , y ) for x , y in self . get_projected_points ( ) ] ) ) <EOL> def length ( self ) : <EOL> """<STR_LIT>""" <EOL> ret = <NUM_LIT:0> <EOL> for i in range ( len ( self . nd_ids ) - <NUM_LIT:1> ) : <EOL> thisnode = self . osm . nodes [ self . nd_ids [ i ] ] <EOL> nextnode = self . osm . nodes [ self . nd_ids [ i + <NUM_LIT:1> ] ] <EOL> ret += vincenty ( thisnode . lat , thisnode . lon , nextnode . lat , nextnode . lon ) <EOL> return ret <EOL> def length_haversine ( self ) : <EOL> ret = <NUM_LIT:0> <EOL> for i in range ( len ( self . nds ) - <NUM_LIT:1> ) : <EOL> thisnode = self . osm . nodes [ self . nds [ i ] ] <EOL> nextnode = self . osm . nodes [ self . nds [ i + <NUM_LIT:1> ] ] <EOL> ret += dist ( thisnode . lon , thisnode . lat , nextnode . lon , nextnode . lat ) <EOL> return ret <EOL> @ property <EOL> def fromv ( self ) : <EOL> return self . nd_ids [ <NUM_LIT:0> ] <EOL> @ property <EOL> def tov ( self ) : <EOL> return self . nd_ids [ - <NUM_LIT:1> ] <EOL> def __repr__ ( self ) : <EOL> return "<STR_LIT>" % ( self . id , len ( self . nd_ids ) , len ( self . tags ) ) <EOL> class OSM : <EOL> def __init__ ( self , filename_or_stream , tolerant = False ) : <EOL> """<STR_LIT>""" <EOL> nodes = { } <EOL> ways = { } <EOL> superself = self <EOL> class OSMHandler ( xml . sax . ContentHandler ) : <EOL> @ classmethod <EOL> def setDocumentLocator ( self , loc ) : <EOL> pass <EOL> @ classmethod <EOL> def startDocument ( self ) : <EOL> pass <EOL> @ classmethod <EOL> def endDocument ( self ) : <EOL> pass <EOL> @ classmethod <EOL> def startElement ( self , name , attrs ) : <EOL> if name == '<STR_LIT>' : <EOL> self . currElem = Node ( attrs [ '<STR_LIT:id>' ] , float ( attrs [ '<STR_LIT>' ] ) , float ( attrs [ '<STR_LIT>' ] ) ) <EOL> elif name == '<STR_LIT>' : <EOL> self . currElem = Way ( attrs [ '<STR_LIT:id>' ] , superself , tolerant ) <EOL> elif name == '<STR_LIT>' : <EOL> self . currElem . tags [ attrs [ '<STR_LIT:k>' ] ] = attrs [ '<STR_LIT:v>' ] <EOL> elif name == '<STR_LIT>' : <EOL> self . currElem . nd_ids . append ( attrs [ '<STR_LIT>' ] ) <EOL> @ classmethod <EOL> def endElement ( self , name ) : <EOL> if name == '<STR_LIT>' : <EOL> nodes [ self . currElem . id ] = self . currElem <EOL> elif name == '<STR_LIT>' : <EOL> ways [ self . currElem . id ] = self . currElem <EOL> @ classmethod <EOL> def characters ( self , chars ) : <EOL> pass <EOL> xml . sax . parse ( filename_or_stream , OSMHandler ) <EOL> self . nodes = nodes <EOL> self . ways = ways <EOL> node_histogram = dict . fromkeys ( self . nodes . keys ( ) , <NUM_LIT:0> ) <EOL> todel = [ ] <EOL> for way in self . ways . values ( ) : <EOL> if len ( way . nd_ids ) < <NUM_LIT:2> : <EOL> todel . append ( way . id ) <EOL> for way_id in todel : <EOL> del self . ways [ way_id ] <EOL> for way in self . ways . values ( ) : <EOL> for node in way . nd_ids : <EOL> try : <EOL> node_histogram [ node ] += <NUM_LIT:1> <EOL> except KeyError : <EOL> node_histogram [ node ] = <NUM_LIT:1> <EOL> new_ways = { } <EOL> for id , way in self . ways . items ( ) : <EOL> split_ways = way . split ( node_histogram ) <EOL> for split_way in split_ways : <EOL> new_ways [ split_way . id ] = split_way <EOL> self . ways = new_ways <EOL> @ property <EOL> def connecting_nodes ( self ) : <EOL> """<STR_LIT>""" <EOL> ret = { } <EOL> for way in self . ways . values ( ) : <EOL> ret [ way . fromv ] = self . nodes [ way . fromv ] <EOL> ret [ way . tov ] = self . nodes [ way . tov ] <EOL> return ret . values ( ) <EOL> @ classmethod <EOL> def download_from_bbox ( cls , left , bottom , right , top ) : <EOL> """<STR_LIT>""" <EOL> fp = download_osm ( left , bottom , right , top ) <EOL> osm = cls ( fp ) <EOL> fp . close ( ) <EOL> return osm <EOL> def find_nearest_node ( self , lng , lat ) : <EOL> """<STR_LIT>""" <EOL> best = self . nodes [ self . ways [ self . ways . keys ( ) [ <NUM_LIT:0> ] ] . nd_ids [ <NUM_LIT:0> ] ] <EOL> bdist = dist ( best . lon , best . lat , lng , lat ) <EOL> for id , way in self . ways . iteritems ( ) : <EOL> for i in ( <NUM_LIT:0> , - <NUM_LIT:1> ) : <EOL> nd = self . nodes [ way . nd_ids [ i ] ] <EOL> d = dist ( lng , lat , nd . lon , nd . lat ) <EOL> if d < bdist : <EOL> bdist = d <EOL> best = nd <EOL> return best <EOL> @ property <EOL> def bbox ( self ) : <EOL> l = INFINITY <EOL> b = INFINITY <EOL> r = - INFINITY <EOL> t = - INFINITY <EOL> for way in self . ways . values ( ) : <EOL> ll , bb , rr , tt = way . bbox <EOL> l = min ( l , ll ) <EOL> b = min ( b , bb ) <EOL> r = max ( r , rr ) <EOL> t = max ( t , tt ) <EOL> return ( l , b , r , t ) </s>
