class ModifiedOSMReverseGeocoder: def __init__(self, osmdb_filename, range=0.005): self.osmdb = OSMDB(osmdb_filename) self.range = range def __call__(self, lat, lon): #vertex = self.nearest_node(lat, lon, use_index=False, range=self.range) vertex = self.nearest_node(lat, lon, use_index=True, range=self.range) if vertex: return NearbyVertex(*vertex) else: return None def bounds(self): """return tuple representing bounding box of reverse geocoder with form # (left, bottom, right, top)""" return self.osmdb.bounds() def nearest_node(self, lat, lon, use_index=True, range=0.005): c = self.osmdb.get_cursor() if use_index and self.osmdb.index: id = list(self.osmdb.index.nearest((lon, lat), 1))[0] c.execute("SELECT id, lat, lon FROM nodes WHERE id = ?", (id, )) else: c.execute( "SELECT id, lat, lon FROM nodes WHERE " + "endnode_refs > 1 AND lat > ? AND lat < ? AND lon > ? AND lon < ?", (lat - range, lat + range, lon - range, lon + range)) dists = [(nid, nlat, nlon, self.haversine_miles(nlon, nlat, lon, lat)) for nid, nlat, nlon in c] if not dists: return (None, None, None, None) return min(dists, key=lambda x: x[3]) def haversine_miles(self, lon1, lat1, lon2, lat2): """Calculate the great circle distance between two points on the earth (specified in decimal degrees)""" # convert decimal degrees to radians lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) # haversine formula dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2 c = 2 * atan2(sqrt(a), sqrt(1 - a)) miles = 3963.0 * c return miles
class ModifiedOSMReverseGeocoder: def __init__(self, osmdb_filename, range=0.005): self.osmdb = OSMDB(osmdb_filename) self.range = range def __call__(self, lat, lon): #vertex = self.nearest_node(lat, lon, use_index=False, range=self.range) vertex = self.nearest_node(lat, lon, use_index=True, range=self.range) if vertex: return NearbyVertex(*vertex) else: return None def bounds(self): """return tuple representing bounding box of reverse geocoder with form # (left, bottom, right, top)""" return self.osmdb.bounds() def nearest_node(self, lat, lon, use_index=True, range=0.005): c = self.osmdb.get_cursor() if use_index and self.osmdb.index: id = list(self.osmdb.index.nearest((lon, lat), 1))[0] c.execute("SELECT id, lat, lon FROM nodes WHERE id = ?", (id,)) else: c.execute("SELECT id, lat, lon FROM nodes WHERE " + "endnode_refs > 1 AND lat > ? AND lat < ? AND lon > ? AND lon < ?", (lat-range, lat+range, lon-range, lon+range)) dists = [(nid, nlat, nlon, self.haversine_miles(nlon, nlat, lon, lat)) for nid, nlat, nlon in c] if not dists: return (None, None, None, None) return min(dists, key=lambda x:x[3]) def haversine_miles(self, lon1, lat1, lon2, lat2): """Calculate the great circle distance between two points on the earth (specified in decimal degrees)""" # convert decimal degrees to radians lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2]) # haversine formula dlon = lon2 - lon1 dlat = lat2 - lat1 a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2 c = 2 * atan2(sqrt(a), sqrt(1 - a)) miles = 3963.0 * c return miles
class OSMReverseGeocoder: def __init__(self, osmdb_filename): self.osmdb = OSMDB( osmdb_filename ) def __call__(self, lat, lon): nearby_vertex = list(self.osmdb.nearest_node(lat, lon)) return "osm-%s"%(nearby_vertex[0]) def bounds(self): """return tuple representing bounding box of reverse geocoder with form (left, bottom, right, top)""" return self.osmdb.bounds()
class OSMReverseGeocoder: def __init__(self, osmdb_filename): self.osmdb = OSMDB(osmdb_filename) def __call__(self, lat, lon): nearby_vertex = list(self.osmdb.nearest_node(lat, lon)) return "osm-%s" % (nearby_vertex[0]) def bounds(self): """return tuple representing bounding box of reverse geocoder with form (left, bottom, right, top)""" return self.osmdb.bounds()
class ContourServer(Servable): def __init__(self, settings_filename): settings = yaml.load( open( settings_filename ) ) self.home_point = settings['center'] # create cache of osm-node positions self.osmdb = OSMDB( settings['osmdb_filename'] ) self.gtfsdb = GTFSDatabase( settings['gtfsdb_filename'] ) self.port = settings['port'] self.node_positions = {} self.index = Rtree() for node_id, tags, lat, lon in self.osmdb.nodes(): self.node_positions[node_id] = (lon,lat) self.index.add( int(node_id), (lon,lat,lon,lat) ) # incarnate graph from graphdb graphdb = GraphDatabase( settings['graphdb_filename'] ) self.graph = graphdb.incarnate() def strgraph(self): return str(self.graph) def vertices(self): return "\n".join( [vv.label for vv in self.graph.vertices] ) def _get_important_routes(self, spt): # set edge thicknesses t0 = time.time() print "setting thicknesses" spt.set_thicknesses( vertex_label ) t1 = time.time() print "took %s"%(t1-t0) t0 = time.time() print "finding gateway boardings" # use thicknesses to determine important boardings origin = spt.get_vertex( vertex_label ) sum_thickness = sum( [edge.thickness for edge in origin.outgoing] ) important_boardings = sorted( filter(lambda x: x.payload.__class__==core.TripBoard and \ x.thickness/float(sum_thickness) > 0.01, spt.edges), key = lambda x:x.thickness ) for edge in important_boardings: print "gateway to %f%% vertices"%(100*edge.thickness/float(sum_thickness)) print "hop onto trip '%s' at stop '%s', time '%s'"%(edge.to_v.payload.trip_id, edge.from_v.label, edge.to_v.payload.time) print "took %ss"%(time.time()-t0) def _points(self, vertex_label, starttime, cutoff, speed): starttime = starttime or time.time() #=== find shortest path tree === print "Finding shortest path tree" t0 = time.time() wo = WalkOptions() wo.walking_speed = speed spt = self.graph.shortest_path_tree( vertex_label, None, State(1,starttime), wo, maxtime=starttime+int(cutoff*1.25) ) wo.destroy() t1 = time.time() print "took %s s"%(t1-t0) #=== cobble together ETA surface === print "Creating ETA surface from OSM points..." points = [] t0 = time.time() for vertex in spt.vertices: if "osm" in vertex.label: x, y = self.node_positions[vertex.label[3:]] points.append( (x, y, vertex.payload.time-starttime) ) t1 = time.time() print "Took %s s"%(t1-t0) spt.destroy() return points def _contour(self, vertex_label, starttime, cutoff, step=None, speed=0.85): points = self._points( vertex_label, starttime, cutoff, speed ) #=== create contour === print "creating contour...", t0 = time.time() contours = travel_time_contour( points, cutoff=cutoff, cellsize=0.004, fudge=1.7, step=step ) print "%s sec"%(time.time()-t0) print "done. here you go..." return contours def label_contour(self, vertex_label, starttime=None, cutoff=1800): starttime = starttime or time.time() return json.dumps( self._contour( vertex_label, starttime, cutoff ) ) def contour(self, lat, lon, year, month, day, hour, minute, second, cutoff, step=60*15, encoded=False, speed=0.85): if step is not None and step < 600: raise Exception( "Step cannot be less than 600 seconds" ) starttime = TimeHelpers.localtime_to_unix( year, month, day, hour, minute, second, "America/Los_Angeles" ) #=== get osm vertex == print( "getting nearest vertex" ) #find osmid of origin intersection t0 = time.time() range = 0.001 bbox = (lon-range, lat-range, lon+range, lat+range) candidates = self.index.intersection( bbox ) vlabel, vlat, vlon, vdist = self.osmdb.nearest_of( lat, lon, candidates ) t1 = time.time() print( "done, took %s seconds"%(t1-t0) ) #vlabel, vlat, vlon, vdist = self.osmdb.nearest_node( lat, lon ) if vlabel is None: return json.dumps( "NO NEARBY INTERSECTION" ) print( "found - %s"%vlabel ) contours = self._contour( "osm"+vlabel, starttime, cutoff, step, speed ) if encoded: encoded_contours = [] for contour in contours: encoded_contour = [] for ring in contour: encoded_contour.append( encode_pairs( [(lat,lon) for lon,lat in ring] ) ) encoded_contours.append( encoded_contour ) contours = encoded_contours return json.dumps( contours ) def _surface(self, lat, lon, year, month, day, hour, minute, second, cutoff, speed, cellsize=0.004): starttime = TimeHelpers.localtime_to_unix( year, month, day, hour, minute, second, "America/Los_Angeles" ) #=== get osm vertex == print( "getting nearest vertex" ) #find osmid of origin intersection t0 = time.time() range = 0.001 bbox = (lon-range, lat-range, lon+range, lat+range) candidates = self.index.intersection( bbox ) vlabel, vlat, vlon, vdist = self.osmdb.nearest_of( lat, lon, candidates ) t1 = time.time() print( "done, took %s seconds"%(t1-t0) ) #vlabel, vlat, vlon, vdist = self.osmdb.nearest_node( lat, lon ) if vlabel is None: return json.dumps( "NO NEARBY INTERSECTION" ) print( "found - %s"%vlabel ) #=== get points which comprise ETA surface === points = self._points( "osm"+vlabel, starttime, cutoff, speed ) #=== create regular grid from ETA surface === print "creating surface...", t0 = time.time() ret = points_to_surface_grid( points, cutoff=cutoff, fudge=1.1, margin=2, closure_tolerance=0.05, cellsize=cellsize ) #ret = travel_time_surface( points, cutoff=cutoff, cellsize=0.004, fudge=1.7 ) print "%s sec"%(time.time()-t0) print "done. here you go..." return ret def surface(self, lat, lon, year, month, day, hour, minute, second, cutoff, speed=0.85): return json.dumps( self._surface(lat,lon,year,month,day,hour,minute,second,cutoff,speed).to_matrix() ) def transitability(self, lat, lon, year, month, day, hour, minute, second, cutoff, speed=0.85): grid = self._surface(lat,lon,year,month,day,hour,minute,second,cutoff,speed) if type(grid) == str: return None ret = 0 for i in range(10): contourslice=sum( [len(filter(lambda x:x[2]<=(cutoff/10.0)*(i+1),col)) for col in grid] ) print contourslice ret += contourslice return ret def transitability_surface(self, left, bottom, right, top, res, year, month, day, hour, minute, second, cutoff, speed=0.85): step = (right-left)/res return json.dumps([[(lon,lat,self.transitability(lat,lon,year,month,day,hour,minute,second,cutoff,speed)) for lat in frange(bottom,top,step)] for lon in frange(left,right,step)]) def nodes(self): return "\n".join( ["%s-%s"%(k,v) for k,v in self.node_positions.items()] ) def nearest_node(self, lat, lon): range = 0.005 bbox = (lon-range, lat-range, lon+range, lat+range) print bbox print self.index.intersection( bbox ) return json.dumps(self.osmdb.nearest_node( lat, lon )) def bounds(self): return json.dumps(self.osmdb.bounds()) def run_test_server(self): Servable.run_test_server(self, self.port)
class RouteServer(Servable): def __init__(self, ch_basename, osmdb_filename, profiledb_filename): graphdb = GraphDatabase( graphdb_filename ) self.osmdb = OSMDB( osmdb_filename ) self.profiledb = ProfileDB( profiledb_filename ) self.ch = reincarnate_ch( ch_basename ) self.shortcut_cache = ShortcutCache( ch_basename+".scc" ) def vertices(self): return "\n".join( [vv.label for vv in self.graph.vertices] ) vertices.mime = "text/plain" def path(self, lat1, lng1, lat2, lng2, transfer_penalty=0, walking_speed=1.0, hill_reluctance=20, narrative=True, jsoncallback=None): t0 = time.time() origin = "osm-%s"%self.osmdb.nearest_node( lat1, lng1 )[0] dest = "osm-%s"%self.osmdb.nearest_node( lat2, lng2 )[0] endpoint_find_time = time.time()-t0 print origin, dest t0 = time.time() wo = WalkOptions() #wo.transfer_penalty=transfer_penalty #wo.walking_speed=walking_speed wo.walking_speed=4 wo.walking_overage = 0 wo.hill_reluctance = 20 wo.turn_penalty = 15 edgepayloads = self.ch.shortest_path( origin, dest, State(1,0), wo ) wo.destroy() route_find_time = time.time()-t0 t0 = time.time() names = [] geoms = [] profile = Profile() total_dist = 0 total_elev = 0 if narrative: names, total_dist = get_full_route_narrative( self.osmdb, edgepayloads ) for edgepayload in edgepayloads: geom, profile_seg = self.shortcut_cache.get( edgepayload.external_id ) #geom = get_ep_geom( self.osmdb, edgepayload ) #profile_seg = get_ep_profile( self.profiledb, edgepayload ) geoms.extend( geom ) profile.add( profile_seg ) route_desc_time = time.time()-t0 ret = json.dumps( (names, encode_pairs( [(lat, lon) for lon, lat in geoms] ), profile.concat(300), { 'route_find_time':route_find_time, 'route_desc_time':route_desc_time, 'endpoint_find_time':endpoint_find_time,}, { 'total_dist':total_dist, 'total_elev':total_elev}) ) if jsoncallback: return "%s(%s)"%(jsoncallback,ret) else: return ret """ def path_raw(self, origin, dest, currtime): wo = WalkOptions() spt = self.graph.shortest_path_tree( origin, dest, State(1,currtime), wo ) wo.destroy() vertices, edges = spt.path( dest ) ret = "\n".join([str(x) for x in vertices]) + "\n\n" + "\n".join([str(x) for x in edges]) spt.destroy() return ret """ def bounds(self, jsoncallback=None): ret = json.dumps( self.osmdb.bounds() ) if jsoncallback: return "%s(%s)"%(jsoncallback,ret) else: return ret
class RouteServer(Servable): def __init__(self, ch_basename, osmdb_filename, profiledb_filename): graphdb = GraphDatabase(graphdb_filename) self.osmdb = OSMDB(osmdb_filename) self.profiledb = ProfileDB(profiledb_filename) self.ch = reincarnate_ch(ch_basename) self.shortcut_cache = ShortcutCache(ch_basename + ".scc") def vertices(self): return "\n".join([vv.label for vv in self.graph.vertices]) vertices.mime = "text/plain" def path(self, lat1, lng1, lat2, lng2, transfer_penalty=0, walking_speed=1.0, hill_reluctance=20, narrative=True, jsoncallback=None): t0 = time.time() origin = "osm-%s" % self.osmdb.nearest_node(lat1, lng1)[0] dest = "osm-%s" % self.osmdb.nearest_node(lat2, lng2)[0] endpoint_find_time = time.time() - t0 print origin, dest t0 = time.time() wo = WalkOptions() #wo.transfer_penalty=transfer_penalty #wo.walking_speed=walking_speed wo.walking_speed = 4 wo.walking_overage = 0 wo.hill_reluctance = 20 wo.turn_penalty = 15 edgepayloads = self.ch.shortest_path(origin, dest, State(1, 0), wo) wo.destroy() route_find_time = time.time() - t0 t0 = time.time() names = [] geoms = [] profile = Profile() total_dist = 0 total_elev = 0 if narrative: names, total_dist = get_full_route_narrative( self.osmdb, edgepayloads) for edgepayload in edgepayloads: geom, profile_seg = self.shortcut_cache.get( edgepayload.external_id) #geom = get_ep_geom( self.osmdb, edgepayload ) #profile_seg = get_ep_profile( self.profiledb, edgepayload ) geoms.extend(geom) profile.add(profile_seg) route_desc_time = time.time() - t0 ret = json.dumps( (names, encode_pairs([(lat, lon) for lon, lat in geoms]), profile.concat(300), { 'route_find_time': route_find_time, 'route_desc_time': route_desc_time, 'endpoint_find_time': endpoint_find_time, }, { 'total_dist': total_dist, 'total_elev': total_elev })) if jsoncallback: return "%s(%s)" % (jsoncallback, ret) else: return ret """ def path_raw(self, origin, dest, currtime): wo = WalkOptions() spt = self.graph.shortest_path_tree( origin, dest, State(1,currtime), wo ) wo.destroy() vertices, edges = spt.path( dest ) ret = "\n".join([str(x) for x in vertices]) + "\n\n" + "\n".join([str(x) for x in edges]) spt.destroy() return ret """ def bounds(self, jsoncallback=None): ret = json.dumps(self.osmdb.bounds()) if jsoncallback: return "%s(%s)" % (jsoncallback, ret) else: return ret
i = 0 while i < len(l): while isinstance(l[i], ltypes): if not l[i]: l.pop(i) i -= 1 break else: l[i:i + 1] = l[i] i += 1 return ltype(l) if __name__ == '__main__': COLORS = { 'motorway': ((1,0,0,1), 2), 'motorway_link': ((1,0,0,1), 1.5), } out, filename, w, h = sys.argv[1:] db = OSMDB(filename) b = db.bounds() r = GeographicCanvas(int(w), int(h), b, mode='svg', fobj=open(out,'wb')) r.background() for way_id, parent_id, from_nd, to_nd, dist, geom, tags in db.edges(): color, stroke = COLORS.get(tags.get('highway'),((0,0,0,.8),0.8)) r.line(coords=flatten(geom), cstroke=color, stroke=stroke) #r.write_to_png(out)