From: maxious Date: Tue, 01 Mar 2011 12:51:49 +0000 Subject: Add suburb geocode to timingpoints tables too X-Git-Url: http://maxious.lambdacomplex.org/git/?p=bus.git&a=commitdiff&h=d58895669174993fdc73bd3d4f7991215c9ea15d --- Add suburb geocode to timingpoints tables too --- --- /dev/null +++ b/betweenpoint.add.php @@ -1,1 +1,50 @@ +"); + $sql = "INSERT INTO stops (geohash,lat,lng) VALUES ('$geoPo', '$nodelat', '$nodelon')"; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } else { + echo "Inserted new point at $geoPo
"; + } + } + flush(); +?> --- /dev/null +++ b/betweenpoint.delete.php @@ -1,1 +1,33 @@ - +\n"); + } else { + echo "Deleted {$_REQUEST['oldgeopo']}
"; + $updatedroutes = 0; + $result_outdatedroutes = pg_query($conn, "Select * FROM between_stops where points LIKE '%" . $_REQUEST['oldgeopo'] . ";%'"); + while ($outdatedroute = pg_fetch_assoc($result_outdatedroutes)) { + $newpoints = str_replace($_REQUEST['oldgeopo'].';', '', $outdatedroute['points']); + $sql = "UPDATE between_stops set points='$newpoints' where fromlocation = '{$outdatedroute['fromlocation']}' AND tolocation = '{$outdatedroute['tolocation']}' "; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } + echo "updated ".$outdatedroute['fromlocation']."->".$outdatedroute['tolocation']."
"; + + $updatedroutes++; + } + echo "updated $updatedroutes routes
"; + } + } + flush(); +?> --- /dev/null +++ b/betweenpoint.move.php @@ -1,1 +1,95 @@ - +"); + $sql = "UPDATE stops SET geohash='$geoPo', lat='$nodelat', lng='$nodelon', name=null, suburb=null WHERE geohash = '{$_REQUEST['oldgeopo']}'"; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } else if (pg_affected_rows($result) == 0) { + echo ("Error 0 points moved, please refresh page and try again"); + } else { + echo $_REQUEST['oldgeopo'] . " replaced with $geoPo
"; + $updatedroutes = 0; + $result_outdatedroutes = pg_query($conn, "Select * FROM between_stops where points LIKE '%" . $_REQUEST['oldgeopo'] . ";%'"); + while ($outdatedroute = pg_fetch_assoc($result_outdatedroutes)) { + $newpoints = str_replace($_REQUEST['oldgeopo'], $geoPo, $outdatedroute['points']); + $sql = "UPDATE between_stops set points='$newpoints' where + fromlocation = '".pg_escape_string($outdatedroute['fromlocation']). + "' AND tolocation = '".pg_escape_string($outdatedroute['tolocation'])."' "; + $result = pg_query($conn, $sql); + if (!$result) { + echo("Error in SQL query: " . pg_last_error() . "
\n"); + } + echo "updated ".$outdatedroute['fromlocation']."->".$outdatedroute['tolocation']."
"; + $updatedroutes++; + } + echo "updated $updatedroutes routes
"; + } + } + flush(); +?> --- a/betweenpoint.php +++ b/betweenpoint.php @@ -10,11 +10,46 @@ // create the ol map object var map = new OpenLayers.Map('map'); - var osmtiles = new OpenLayers.Layer.OSM("local", "http://127.0.0.1/tiles/${z}/${x}/${y}.png") + var osmtiles = new OpenLayers.Layer.OSM("local", "/tiles/${z}/${x}/${y}.png") // use http://open.atlas.free.fr/GMapsTransparenciesImgOver.php and http://code.google.com/p/googletilecutter/ to make tiles markers = new OpenLayers.Layer.Markers("Between Stop Markers"); - + //hanlde mousedown on regions that are not points by reporting latlng +OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, { + defaultHandlerOptions: { + 'single': true, + 'double': false, + 'pixelTolerance': 0, + 'stopSingle': false, + 'stopDouble': false + }, + + initialize: function(options) { + this.handlerOptions = OpenLayers.Util.extend( + {}, this.defaultHandlerOptions + ); + OpenLayers.Control.prototype.initialize.apply( + this, arguments + ); + this.handler = new OpenLayers.Handler.Click( + this, { + 'click': this.trigger + }, this.handlerOptions + ); + }, + + trigger: function(e) { + var lonlat = map.getLonLatFromViewPortPx(e.xy).transform( + new OpenLayers.Projection("EPSG:900913"), + new OpenLayers.Projection("EPSG:4326") + ); + $('form input[name="newlatlng"]').val(lonlat.lat + ";" + lonlat.lon ); + } + + }); + var click = new OpenLayers.Control.Click(); + map.addControl(click); + click.activate(); -var timeicon = new OpenLayers.Icon("http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png",new OpenLayers.Size(32,32)); +var timeicon = new OpenLayers.Icon("icong.png",new OpenLayers.Size(16,16)); var timepoints = new OpenLayers.Layer.GeoRSS("Timing Points", "displaytimepoints.georss.php", { icon: timeicon }); map.addLayers([osmtiles, markers,timepoints]); @@ -51,11 +88,31 @@ function submitBetween () { $.post("betweenpoint.submit.php", $("#inputform").serialize(), function(html){ $("#response").html(html); - //clearForms(); - return false; - }); -}; - + clearForms(); + return false; + }); +}; +function submitMove () { + $.post("betweenpoint.move.php", $("#moveform").serialize(), function(html){ + $("#response").html(html); + clearForms(); + return false; + }); +}; +function submitDelete () { + $.post("betweenpoint.delete.php", $("#moveform").serialize(), function(html){ + $("#response").html(html); + clearForms(); + return false; + }); +}; +function submitAdd () { + $.post("betweenpoint.add.php", $("#moveform").serialize(), function(html){ + $("#response").html(html); + clearForms(); + return false; + }); +}; function OnChange(dropdown) { var myindex = dropdown.selectedIndex @@ -146,10 +203,11 @@ } - + $processed = 0; foreach ($paths as $path => $routes) { if (!in_array($path, array_keys($completedPaths))) { - echo "\n"; + echo "\n"; + $processed++; } else { $completedRoutes = explode(";", $completedPaths[$path]); $incompleteRoutes = ""; @@ -161,13 +219,14 @@ } if ($incompleteRoutes != "") { - echo "\n"; + echo "\n"; + $processed++; } } } + echo "$processed"; ?> - from to
@@ -178,6 +237,13 @@
+
+oldgeopo +newlatlng + + + +
--- a/betweenpoint.submit.php +++ b/betweenpoint.submit.php @@ -5,9 +5,9 @@ exit; } print_r($_REQUEST); -$reverse=$_REQUEST["reverse"]; -$from=$_REQUEST["from"]; -$to=$_REQUEST["to"]; +$reverse=(isset($_REQUEST["reverse"]) ? $_REQUEST["reverse"] : "off"); +$from=pg_escape_string($_REQUEST["from"]); +$to=pg_escape_string($_REQUEST["to"]); $routes=$_REQUEST["routes"] ; $points=$_REQUEST["between_points"]; $sql = "INSERT INTO between_stops (fromLocation, toLocation, points, routes) VALUES('$from','$to','$points','$routes')"; --- a/busui/about.php +++ /dev/null @@ -1,9 +1,1 @@ - -

-Some icons by Joseph Wain / glyphish.com - --- a/busui/common.inc.php +++ /dev/null @@ -1,315 +1,1 @@ -"; -} -function isFastDevice() { - return true; -} - -function include_header($pageTitle, $opendiv = true, $geolocate = false) { - // if (isDebug()) // set php error level high - echo ' - - - - bus.lambdacomplex.org - '.$pageTitle.' - - - - - - - - '; - if ($geolocate) { -echo " "; - } -echo ' - - '; -if ($opendiv) echo '

- -
-

'.$pageTitle.'

-
-
'; -} - -function include_footer() -{ - echo '
'; -} - -function service_period() -{ -switch (date('w')){ - -case 0: - return 'sunday'; -case 6: - return 'saturday'; -default: - return 'weekday'; -} -} - -function midnight_seconds() -{ -// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html - $secs = (date("G") * 3600) + (date("i") * 60) + date("s"); - return $secs; -} - -function midnight_seconds_to_time($seconds) -{ - $midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y")); - return date("h:ia",$midnight+$seconds); -} -function getPage($url) -{ - $ch = curl_init($url); -curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); -curl_setopt( $ch, CURLOPT_HEADER, 0 ); -$page = curl_exec($ch); -curl_close($ch); -return $page; -} -function array_flatten($a,$f=array()){ - if(!$a||!is_array($a))return ''; - foreach($a as $k=>$v){ - if(is_array($v))$f=array_flatten($v,$f); - else $f[$k]=$v; - } - return $f; -} - -function staticmap($mapPoints, $zoom = 0, $markerImage = "iconb") -{ -$width = 300; -$height = 300; -$metersperpixel[9]=305.492*$width; -$metersperpixel[10]=152.746*$width; -$metersperpixel[11]=76.373*$width; -$metersperpixel[12]=38.187*$width; -$metersperpixel[13]=19.093*$width; -$metersperpixel[14]=9.547*$width; -$metersperpixel[15]=4.773*$width; -$metersperpixel[16]=2.387*$width; -// $metersperpixel[17]=1.193*$width; -$center = ""; -$markers = ""; -$minlat = 999; -$minlon = 999; -$maxlat = 0; -$maxlon = 0; - - if (sizeof($mapPoints) < 1) return "map error"; - if (sizeof($mapPoints) === 1) { - if ($zoom == 0) $zoom = 14; - $markers .= "{$mapPoints[0][0]},{$mapPoints[0][1]},$markerimage"; - $center = "{$mapPoints[0][0]},{$mapPoints[0][1]}"; - } else { - foreach ($mapPoints as $index => $mapPoint) { - $markers .= $mapPoint[0].",".$mapPoint[1].",".$markerImage.($index+1); - if ($index+1 != sizeof($mapPoints)) $markers .= "|"; - if ($mapPoint[0] < $minlat) $minlat = $mapPoint[0]; - if ($mapPoint[0] > $maxlat) $maxlat = $mapPoint[0]; - if ($mapPoint[1] < $minlon) $minlon = $mapPoint[1]; - if ($mapPoint[1] > $maxlon) $maxlon = $mapPoint[1]; - $totalLat += $mapPoint[0]; - $totalLon += $mapPoint[1]; - } - if ($zoom == 0) { - $mapwidthinmeters = distance($minlat,$minlon,$minlat,$maxlon); - foreach (array_reverse($metersperpixel,true) as $zoomLevel => $maxdistance) - { - if ($zoom == 0 && $mapwidthinmeters < ($maxdistance + 50)) $zoom = $zoomLevel; - } - } - $center = $totalLat/sizeof($mapPoints).",".$totalLon/sizeof($mapPoints); - } - - return ''; -} - -function distance($lat1, $lng1, $lat2, $lng2) -{ - $pi80 = M_PI / 180; - $lat1 *= $pi80; - $lng1 *= $pi80; - $lat2 *= $pi80; - $lng2 *= $pi80; - - $r = 6372.797; // mean radius of Earth in km - $dlat = $lat2 - $lat1; - $dlng = $lng2 - $lng1; - $a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlng / 2) * sin($dlng / 2); - $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); - $km = $r * $c; - - return $km * 1000; -} - -function decodePolylineToArray($encoded) -{ -// source: http://latlongeeks.com/forum/viewtopic.php?f=4&t=5 - $length = strlen($encoded); - $index = 0; - $points = array(); - $lat = 0; - $lng = 0; - - while ($index < $length) - { - // Temporary variable to hold each ASCII byte. - $b = 0; - - // The encoded polyline consists of a latitude value followed by a - // longitude value. They should always come in pairs. Read the - // latitude value first. - $shift = 0; - $result = 0; - do - { - // The `ord(substr($encoded, $index++))` statement returns the ASCII - // code for the character at $index. Subtract 63 to get the original - // value. (63 was added to ensure proper ASCII characters are displayed - // in the encoded polyline string, which is `human` readable) - $b = ord(substr($encoded, $index++)) - 63; - - // AND the bits of the byte with 0x1f to get the original 5-bit `chunk. - // Then left shift the bits by the required amount, which increases - // by 5 bits each time. - // OR the value into $results, which sums up the individual 5-bit chunks - // into the original value. Since the 5-bit chunks were reversed in - // order during encoding, reading them in this way ensures proper - // summation. - $result |= ($b & 0x1f) << $shift; - $shift += 5; - } - // Continue while the read byte is >= 0x20 since the last `chunk` - // was not OR'd with 0x20 during the conversion process. (Signals the end) - while ($b >= 0x20); - - // Check if negative, and convert. (All negative values have the last bit - // set) - $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1)); - - // Compute actual latitude since value is offset from previous value. - $lat += $dlat; - - // The next values will correspond to the longitude for this point. - $shift = 0; - $result = 0; - do - { - $b = ord(substr($encoded, $index++)) - 63; - $result |= ($b & 0x1f) << $shift; - $shift += 5; - } - while ($b >= 0x20); - - $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1)); - $lng += $dlng; - - // The actual latitude and longitude values were multiplied by - // 1e5 before encoding so that they could be converted to a 32-bit - // integer representation. (With a decimal accuracy of 5 places) - // Convert back to original values. - $points[] = array($lat * 1e-5, $lng * 1e-5); - } - - return $points; -} - -function object2array($object) { - if (is_object($object)) { - foreach ($object as $key => $value) { - $array[$key] = $value; - } - } - else { - $array = $object; - } - return $array; -} - -function geocode($query, $giveOptions) { - $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?query=".$query."&bbox=-35.5,149.00,-35.15,149.1930&return_location=true&bbox_only=true"; - $contents = json_decode(getPage($url)); - if ($giveOptions) return $contents->features; - elseif (isset($contents->features[0]->centroid)) return $contents->features[0]->centroid->coordinates[0].",".$contents->features[0]->centroid->coordinates[1]; - else return ""; -} - -function reverseGeocode($lat,$lng) { - $url = "http://geocoding.cloudmade.com/daa03470bb8740298d4b10e3f03d63e6/geocoding/v2/find.js?around=".$lat.",".$lng."&distance=closest&object_type=road"; - $contents = json_decode(getPage($url)); - return $contents->features[0]->properties->name; -} - -function startsWith($haystack,$needle,$case=true) { - if($case){return (strcmp(substr($haystack, 0, strlen($needle)),$needle)===0);} - return (strcasecmp(substr($haystack, 0, strlen($needle)),$needle)===0); -} - -function endsWith($haystack,$needle,$case=true) { - if($case){return (strcmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0);} - return (strcasecmp(substr($haystack, strlen($haystack) - strlen($needle)),$needle)===0); -} -?> - - --- a/busui/index.php +++ /dev/null @@ -1,32 +1,1 @@ - -
-
-

logo
- bus.lambdacomplex.org

-
-
- Launch Trip Planner... - - -
- Current Location: Search? Update to Here?
- Time:
- Service Period:
-
-
-
- - --- a/busui/readme.txt +++ /dev/null @@ -1,30 +1,1 @@ -# input location (via GPS or favourites or search) and destination (via searchable list, optional) -# http://10.0.1.153:8765/json/boundboxstops?n=-35.27568499917103&e=149.1346514225006&s=-35.279495003493516 -&w=149.12622928619385&limit=50 -# http://10.0.1.153:8765/json/stoptrips?stop=43&time=64440 # recursively call to show all services nearby, sort by distance, need to filter by service period -# Hey, can pick destination again from a list filtered to places these stops go if you're curious! -# http://10.0.1.153:8765/json/tripstoptimes?trip=2139 # Can recursively call and parse based on intended destination to show ETA -# http://10.0.1.153:8765/json/triprows?trip=2139 # For pretty maps -have to do -/usr/sbin/setsebool -P httpd_can_network_connect=1 -on fedora - -might need http://forum.jquery.com/topic/google-maps-inside-jquery-mobile - -some extras -/json/routes = all routes -/json/neareststops?lat/lng/number -TODO -Destinations -Favourites -OOP stops/routes -Stop sorting/search-filter - -static maps -https://code.google.com/apis/maps/documentation/staticmaps/ -http://www.multimap.com/openapidocs/1.2/web_service/staticmaps.htm -http://dev.openstreetmap.de/staticmap/ (os @ http://sourceforge.net/projects/staticmaplite/) -(php and open source @ http://trac.openstreetmap.org/browser/sites/other/StaticMap?rev=16348) -http://pafciu17.dev.openstreetmap.org/ - --- a/busui/routeList.php +++ /dev/null @@ -1,58 +1,1 @@ - - -
- '; -echo ' \n"; - -include_footer(); -?> - --- a/busui/schedule_viewer.py +++ /dev/null @@ -1,560 +1,1 @@ -#!/usr/bin/python2.5 -# Copyright (C) 2007 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -An example application that uses the transitfeed module. - -You must provide a Google Maps API key. -""" - - -import BaseHTTPServer, sys, urlparse -import bisect -from gtfsscheduleviewer.marey_graph import MareyGraph -import gtfsscheduleviewer -import mimetypes -import os.path -import re -import signal -import simplejson -import socket -import time -import transitfeed -from transitfeed import util -import urllib - - -# By default Windows kills Python with Ctrl+Break. Instead make Ctrl+Break -# raise a KeyboardInterrupt. -if hasattr(signal, 'SIGBREAK'): - signal.signal(signal.SIGBREAK, signal.default_int_handler) - - -mimetypes.add_type('text/plain', '.vbs') - - -class ResultEncoder(simplejson.JSONEncoder): - def default(self, obj): - try: - iterable = iter(obj) - except TypeError: - pass - else: - return list(iterable) - return simplejson.JSONEncoder.default(self, obj) - -# Code taken from -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/425210/index_txt -# An alternate approach is shown at -# http://mail.python.org/pipermail/python-list/2003-July/212751.html -# but it requires multiple threads. A sqlite object can only be used from one -# thread. -class StoppableHTTPServer(BaseHTTPServer.HTTPServer): - def server_bind(self): - BaseHTTPServer.HTTPServer.server_bind(self) - self.socket.settimeout(1) - self._run = True - - def get_request(self): - while self._run: - try: - sock, addr = self.socket.accept() - sock.settimeout(None) - return (sock, addr) - except socket.timeout: - pass - - def stop(self): - self._run = False - - def serve(self): - while self._run: - self.handle_request() - - -def StopToTuple(stop): - """Return tuple as expected by javascript function addStopMarkerFromList""" - return (stop.stop_id, stop.stop_name, float(stop.stop_lat), - float(stop.stop_lon), stop.location_type) - - -class ScheduleRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def do_GET(self): - scheme, host, path, x, params, fragment = urlparse.urlparse(self.path) - parsed_params = {} - for k in params.split('&'): - k = urllib.unquote(k) - if '=' in k: - k, v = k.split('=', 1) - parsed_params[k] = unicode(v, 'utf8') - else: - parsed_params[k] = '' - - if path == '/': - return self.handle_GET_home() - - m = re.match(r'/json/([a-z]{1,64})', path) - if m: - handler_name = 'handle_json_GET_%s' % m.group(1) - handler = getattr(self, handler_name, None) - if callable(handler): - return self.handle_json_wrapper_GET(handler, parsed_params) - - # Restrict allowable file names to prevent relative path attacks etc - m = re.match(r'/file/([a-z0-9_-]{1,64}\.?[a-z0-9_-]{1,64})$', path) - if m and m.group(1): - try: - f, mime_type = self.OpenFile(m.group(1)) - return self.handle_static_file_GET(f, mime_type) - except IOError, e: - print "Error: unable to open %s" % m.group(1) - # Ignore and treat as 404 - - m = re.match(r'/([a-z]{1,64})', path) - if m: - handler_name = 'handle_GET_%s' % m.group(1) - handler = getattr(self, handler_name, None) - if callable(handler): - return handler(parsed_params) - - return self.handle_GET_default(parsed_params, path) - - def OpenFile(self, filename): - """Try to open filename in the static files directory of this server. - Return a tuple (file object, string mime_type) or raise an exception.""" - (mime_type, encoding) = mimetypes.guess_type(filename) - assert mime_type - # A crude guess of when we should use binary mode. Without it non-unix - # platforms may corrupt binary files. - if mime_type.startswith('text/'): - mode = 'r' - else: - mode = 'rb' - return open(os.path.join(self.server.file_dir, filename), mode), mime_type - - def handle_GET_default(self, parsed_params, path): - self.send_error(404) - - def handle_static_file_GET(self, fh, mime_type): - content = fh.read() - self.send_response(200) - self.send_header('Content-Type', mime_type) - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - def AllowEditMode(self): - return False - - def handle_GET_home(self): - schedule = self.server.schedule - (min_lat, min_lon, max_lat, max_lon) = schedule.GetStopBoundingBox() - forbid_editing = ('true', 'false')[self.AllowEditMode()] - - agency = ', '.join(a.agency_name for a in schedule.GetAgencyList()).encode('utf-8') - - key = self.server.key - host = self.server.host - - # A very simple template system. For a fixed set of values replace [xxx] - # with the value of local variable xxx - f, _ = self.OpenFile('index.html') - content = f.read() - for v in ('agency', 'min_lat', 'min_lon', 'max_lat', 'max_lon', 'key', - 'host', 'forbid_editing'): - content = content.replace('[%s]' % v, str(locals()[v])) - - self.send_response(200) - self.send_header('Content-Type', 'text/html') - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - def handle_json_GET_routepatterns(self, params): - """Given a route_id generate a list of patterns of the route. For each - pattern include some basic information and a few sample trips.""" - schedule = self.server.schedule - route = schedule.GetRoute(params.get('route', None)) - if not route: - self.send_error(404) - return - time = int(params.get('time', 0)) - sample_size = 10 # For each pattern return the start time for this many trips - - pattern_id_trip_dict = route.GetPatternIdTripDict() - patterns = [] - - for pattern_id, trips in pattern_id_trip_dict.items(): - time_stops = trips[0].GetTimeStops() - if not time_stops: - continue - has_non_zero_trip_type = False; - for trip in trips: - if trip['trip_type'] and trip['trip_type'] != '0': - has_non_zero_trip_type = True - name = u'%s to %s, %d stops' % (time_stops[0][2].stop_name, time_stops[-1][2].stop_name, len(time_stops)) - transitfeed.SortListOfTripByTime(trips) - - num_trips = len(trips) - if num_trips <= sample_size: - start_sample_index = 0 - num_after_sample = 0 - else: - # Will return sample_size trips that start after the 'time' param. - - # Linear search because I couldn't find a built-in way to do a binary - # search with a custom key. - start_sample_index = len(trips) - for i, trip in enumerate(trips): - if trip.GetStartTime() >= time: - start_sample_index = i - break - - num_after_sample = num_trips - (start_sample_index + sample_size) - if num_after_sample < 0: - # Less than sample_size trips start after 'time' so return all the - # last sample_size trips. - num_after_sample = 0 - start_sample_index = num_trips - sample_size - - sample = [] - for t in trips[start_sample_index:start_sample_index + sample_size]: - sample.append( (t.GetStartTime(), t.trip_id) ) - - patterns.append((name, pattern_id, start_sample_index, sample, - num_after_sample, (0,1)[has_non_zero_trip_type])) - - patterns.sort() - return patterns - - def handle_json_wrapper_GET(self, handler, parsed_params): - """Call handler and output the return value in JSON.""" - schedule = self.server.schedule - result = handler(parsed_params) - content = ResultEncoder().encode(result) - self.send_response(200) - self.send_header('Content-Type', 'text/plain') - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - def handle_json_GET_routes(self, params): - """Return a list of all routes.""" - schedule = self.server.schedule - result = [] - for r in schedule.GetRouteList(): - servicep = None - for t in schedule.GetTripList(): - if t.route_id == r.route_id: - servicep = t.service_period - break - result.append( (r.route_id, r.route_short_name, r.route_long_name, servicep.service_id) ) - result.sort(key = lambda x: x[1:3]) - return result - - def handle_json_GET_routerow(self, params): - schedule = self.server.schedule - route = schedule.GetRoute(params.get('route', None)) - return [transitfeed.Route._FIELD_NAMES, route.GetFieldValuesTuple()] - - def handle_json_GET_routetrips(self, params): - """ Get a trip for a route_id (preferablly the next one) """ - schedule = self.server.schedule - query = params.get('route_id', None).lower() - result = [] - for t in schedule.GetTripList(): - if t.route_id == query: - result.append ( (t.GetStartTime(), t.trip_id) ) - return sorted(result, key=lambda trip: trip[0]) - - def handle_json_GET_triprows(self, params): - """Return a list of rows from the feed file that are related to this - trip.""" - schedule = self.server.schedule - try: - trip = schedule.GetTrip(params.get('trip', None)) - except KeyError: - # if a non-existent trip is searched for, the return nothing - return - route = schedule.GetRoute(trip.route_id) - trip_row = dict(trip.iteritems()) - route_row = dict(route.iteritems()) - return [['trips.txt', trip_row], ['routes.txt', route_row]] - - def handle_json_GET_tripstoptimes(self, params): - schedule = self.server.schedule - try: - trip = schedule.GetTrip(params.get('trip')) - except KeyError: - # if a non-existent trip is searched for, the return nothing - return - time_stops = trip.GetTimeStops() - stops = [] - times = [] - for arr,dep,stop in time_stops: - stops.append(StopToTuple(stop)) - times.append(arr) - return [stops, times] - - def handle_json_GET_tripshape(self, params): - schedule = self.server.schedule - try: - trip = schedule.GetTrip(params.get('trip')) - except KeyError: - # if a non-existent trip is searched for, the return nothing - return - points = [] - if trip.shape_id: - shape = schedule.GetShape(trip.shape_id) - for (lat, lon, dist) in shape.points: - points.append((lat, lon)) - else: - time_stops = trip.GetTimeStops() - for arr,dep,stop in time_stops: - points.append((stop.stop_lat, stop.stop_lon)) - return points - - def handle_json_GET_neareststops(self, params): - """Return a list of the nearest 'limit' stops to 'lat', 'lon'""" - schedule = self.server.schedule - lat = float(params.get('lat')) - lon = float(params.get('lon')) - limit = int(params.get('limit')) - stops = schedule.GetNearestStops(lat=lat, lon=lon, n=limit) - return [StopToTuple(s) for s in stops] - - def handle_json_GET_boundboxstops(self, params): - """Return a list of up to 'limit' stops within bounding box with 'n','e' - and 's','w' in the NE and SW corners. Does not handle boxes crossing - longitude line 180.""" - schedule = self.server.schedule - n = float(params.get('n')) - e = float(params.get('e')) - s = float(params.get('s')) - w = float(params.get('w')) - limit = int(params.get('limit')) - stops = schedule.GetStopsInBoundingBox(north=n, east=e, south=s, west=w, n=limit) - return [StopToTuple(s) for s in stops] - - def handle_json_GET_stops(self, params): - schedule = self.server.schedule - return [StopToTuple(s) for s in schedule.GetStopList()] - - def handle_json_GET_timingpoints(self, params): - schedule = self.server.schedule - matches = [] - for s in schedule.GetStopList(): - if s.stop_code.find("Wj") == -1: - matches.append(StopToTuple(s)) - return matches - - def handle_json_GET_stopsearch(self, params): - schedule = self.server.schedule - query = params.get('q', None).lower() - matches = [] - for s in schedule.GetStopList(): - if s.stop_id.lower().find(query) != -1 or s.stop_name.lower().find(query) != -1: - matches.append(StopToTuple(s)) - return matches - - def handle_json_GET_stop(self, params): - schedule = self.server.schedule - query = params.get('stop_id', None).lower() - for s in schedule.GetStopList(): - if s.stop_id.lower() == query: - return StopToTuple(s) - return [] - - def handle_json_GET_stoptrips(self, params): - """Given a stop_id and time in seconds since midnight return the next - trips to visit the stop.""" - schedule = self.server.schedule - stop = schedule.GetStop(params.get('stop', None)) - time = int(params.get('time', 0)) - service_period = params.get('service_period', None) - time_trips = stop.GetStopTimeTrips(schedule) - time_trips.sort() # OPT: use bisect.insort to make this O(N*ln(N)) -> O(N) - # Keep the first 15 after param 'time'. - # Need make a tuple to find correct bisect point - time_trips = time_trips[bisect.bisect_left(time_trips, (time, 0)):] - time_trips = time_trips[:15] - # TODO: combine times for a route to show next 2 departure times - result = [] - for time, (trip, index), tp in time_trips: - headsign = None - # Find the most recent headsign from the StopTime objects - for stoptime in trip.GetStopTimes()[index::-1]: - if stoptime.stop_headsign: - headsign = stoptime.stop_headsign - break - # If stop_headsign isn't found, look for a trip_headsign - if not headsign: - headsign = trip.trip_headsign - route = schedule.GetRoute(trip.route_id) - trip_name = '' - if route.route_short_name: - trip_name += route.route_short_name - if route.route_long_name: - if len(trip_name): - trip_name += " - " - trip_name += route.route_long_name - if headsign: - trip_name += " (Direction: %s)" % headsign - if service_period == None or trip.service_id == service_period: - result.append((time, (trip.trip_id, trip_name, trip.service_id), tp)) - return result - - def handle_GET_ttablegraph(self,params): - """Draw a Marey graph in SVG for a pattern (collection of trips in a route - that visit the same sequence of stops).""" - schedule = self.server.schedule - marey = MareyGraph() - trip = schedule.GetTrip(params.get('trip', None)) - route = schedule.GetRoute(trip.route_id) - height = int(params.get('height', 300)) - - if not route: - print 'no such route' - self.send_error(404) - return - - pattern_id_trip_dict = route.GetPatternIdTripDict() - pattern_id = trip.pattern_id - if pattern_id not in pattern_id_trip_dict: - print 'no pattern %s found in %s' % (pattern_id, pattern_id_trip_dict.keys()) - self.send_error(404) - return - triplist = pattern_id_trip_dict[pattern_id] - - pattern_start_time = min((t.GetStartTime() for t in triplist)) - pattern_end_time = max((t.GetEndTime() for t in triplist)) - - marey.SetSpan(pattern_start_time,pattern_end_time) - marey.Draw(triplist[0].GetPattern(), triplist, height) - - content = marey.Draw() - - self.send_response(200) - self.send_header('Content-Type', 'image/svg+xml') - self.send_header('Content-Length', str(len(content))) - self.end_headers() - self.wfile.write(content) - - -def FindPy2ExeBase(): - """If this is running in py2exe return the install directory else return - None""" - # py2exe puts gtfsscheduleviewer in library.zip. For py2exe setup.py is - # configured to put the data next to library.zip. - windows_ending = gtfsscheduleviewer.__file__.find('\\library.zip\\') - if windows_ending != -1: - return transitfeed.__file__[:windows_ending] - else: - return None - - -def FindDefaultFileDir(): - """Return the path of the directory containing the static files. By default - the directory is called 'files'. The location depends on where setup.py put - it.""" - base = FindPy2ExeBase() - if base: - return os.path.join(base, 'schedule_viewer_files') - else: - # For all other distributions 'files' is in the gtfsscheduleviewer - # directory. - base = os.path.dirname(gtfsscheduleviewer.__file__) # Strip __init__.py - return os.path.join(base, 'files') - - -def GetDefaultKeyFilePath(): - """In py2exe return absolute path of file in the base directory and in all - other distributions return relative path 'key.txt'""" - windows_base = FindPy2ExeBase() - if windows_base: - return os.path.join(windows_base, 'key.txt') - else: - return 'key.txt' - - -def main(RequestHandlerClass = ScheduleRequestHandler): - usage = \ -'''%prog [options] [] - -Runs a webserver that lets you explore a in your browser. - -If is omited the filename is read from the console. Dragging -a file into the console may enter the filename. -''' - parser = util.OptionParserLongError( - usage=usage, version='%prog '+transitfeed.__version__) - parser.add_option('--feed_filename', '--feed', dest='feed_filename', - help='file name of feed to load') - parser.add_option('--key', dest='key', - help='Google Maps API key or the name ' - 'of a text file that contains an API key') - parser.add_option('--host', dest='host', help='Host name of Google Maps') - parser.add_option('--port', dest='port', type='int', - help='port on which to listen') - parser.add_option('--file_dir', dest='file_dir', - help='directory containing static files') - parser.add_option('-n', '--noprompt', action='store_false', - dest='manual_entry', - help='disable interactive prompts') - parser.set_defaults(port=8765, - host='maps.google.com', - file_dir=FindDefaultFileDir(), - manual_entry=True) - (options, args) = parser.parse_args() - - if not os.path.isfile(os.path.join(options.file_dir, 'index.html')): - print "Can't find index.html with --file_dir=%s" % options.file_dir - exit(1) - - if not options.feed_filename and len(args) == 1: - options.feed_filename = args[0] - - if not options.feed_filename and options.manual_entry: - options.feed_filename = raw_input('Enter Feed Location: ').strip('"') - - default_key_file = GetDefaultKeyFilePath() - if not options.key and os.path.isfile(default_key_file): - options.key = open(default_key_file).read().strip() - - if options.key and os.path.isfile(options.key): - options.key = open(options.key).read().strip() - - schedule = transitfeed.Schedule(problem_reporter=transitfeed.ProblemReporter()) - print 'Loading data from feed "%s"...' % options.feed_filename - print '(this may take a few minutes for larger cities)' - schedule.Load(options.feed_filename) - - server = StoppableHTTPServer(server_address=('', options.port), - RequestHandlerClass=RequestHandlerClass) - server.key = options.key - server.schedule = schedule - server.file_dir = options.file_dir - server.host = options.host - server.feed_path = options.feed_filename - - print ("To view, point your browser at http://localhost:%d/" % - (server.server_port)) - server.serve_forever() - - -if __name__ == '__main__': - main() - --- a/busui/staticmaplite/.gitignore +++ /dev/null @@ -1,3 +1,1 @@ -cache/tiles -cache/map --- a/busui/staticmaplite/images/markers/GPlotter - Make Google Maps Easily.URL +++ /dev/null @@ -1,3 +1,1 @@ -[InternetShortcut] -URL=http://gplotter.offwhite.net/ --- a/busui/staticmaplite/images/markers/Google Maps Icons, Free!.URL +++ /dev/null @@ -1,3 +1,1 @@ -[InternetShortcut] -URL=http://brennan.offwhite.net/blog/2005/07/23/new-google-maps-icons-free/ --- a/busui/staticmaplite/index.html +++ /dev/null @@ -1,122 +1,1 @@ - - - - - - staticMapLite - - - -
- -
- -
-

- staticMapLite - simple map for your website -

-

-

-

- This image was created using the following simple <img> tag: -

<img src="staticmap.php?center=40.714728,-73.998672&zoom=14&size=865x512&maptype=mapnik" />
-

-
-
-
-

- Place Markers -

- -

- -

Add markers by appending them to the image URL: -

markers=40.702147,-74.015794,lightblue1|40.711614,-74.012318,lightblue2|40.718217,-73.998284,lightblue3
-

-
-
-
-

- Use Different Map Styles (Tile Sources) -

- -

-

- -
maptype=mapnik
-
-
- -
maptype=osmarenderer
-
-
- -
maptype=cycle
-
-
-

-
- -
- -
- - --- a/busui/staticmaplite/selinux-fix.sh +++ /dev/null @@ -1,3 +1,1 @@ -chcon -R -t httpd_sys_content_rw_t cache - --- a/busui/staticmaplite/staticmap.php +++ /dev/null @@ -1,273 +1,1 @@ - - * - * USAGE: - * - * staticmap.php?center=40.714728,-73.998672&zoom=14&size=512x512&maptype=mapnik&markers=40.702147,-74.015794,blues|40.711614,-74.012318,greeng|40.718217,-73.998284,redc - * - */ - -error_reporting(0); -ini_set('display_errors','off'); - -Class staticMapLite { - - protected $tileSize = 256; - protected $tileSrcUrl = array( 'mapnik' => 'http://tile.openstreetmap.org/{Z}/{X}/{Y}.png', - 'osmarenderer' => 'http://c.tah.openstreetmap.org/Tiles/tile/{Z}/{X}/{Y}.png', - 'cycle' => 'http://c.andy.sandbox.cloudmade.com/tiles/cycle/{Z}/{X}/{Y}.png' - ); - - protected $tileDefaultSrc = 'mapnik'; - protected $markerBaseDir = 'images/markers'; - protected $osmLogo = 'images/osm_logo.png'; - - protected $useTileCache = true; - protected $tileCacheBaseDir = './cache/tiles'; - - protected $useMapCache = true; - protected $mapCacheBaseDir = './cache/maps'; - protected $mapCacheID = ''; - protected $mapCacheFile = ''; - protected $mapCacheExtension = 'png'; - - protected $zoom, $lat, $lon, $width, $height, $markers, $image, $maptype; - protected $centerX, $centerY, $offsetX, $offsetY; - - public function __construct(){ - $this->zoom = 0; - $this->lat = 0; - $this->lon = 0; - $this->width = 500; - $this->height = 350; - $this->markers = array(); - $this->maptype = $this->tileDefaultSrc; - } - - public function parseParams(){ - global $_GET; - - // get zoom from GET paramter - $this->zoom = $_GET['zoom']?intval($_GET['zoom']):0; - if($this->zoom>18)$this->zoom = 18; - - // get lat and lon from GET paramter - list($this->lat,$this->lon) = split(',',$_GET['center']); - $this->lat = floatval($this->lat); - $this->lon = floatval($this->lon); - - // get zoom from GET paramter - if($_GET['size']){ - list($this->width, $this->height) = split('x',$_GET['size']); - $this->width = intval($this->width); - $this->height = intval($this->height); - } - if($_GET['markers']){ - $markers = split('%7C|\|',$_GET['markers']); - foreach($markers as $marker){ - list($markerLat, $markerLon, $markerImage) = split(',',$marker); - $markerLat = floatval($markerLat); - $markerLon = floatval($markerLon); - $markerImage = basename($markerImage); - $this->markers[] = array('lat'=>$markerLat, 'lon'=>$markerLon, 'image'=>$markerImage); - } - - } - if($_GET['maptype']){ - if(array_key_exists($_GET['maptype'],$this->tileSrcUrl)) $this->maptype = $_GET['maptype']; - } - } - - public function lonToTile($long, $zoom){ - return (($long + 180) / 360) * pow(2, $zoom); - } - - public function latToTile($lat, $zoom){ - return (1 - log(tan($lat * pi()/180) + 1 / cos($lat* pi()/180)) / pi()) /2 * pow(2, $zoom); - } - - public function initCoords(){ - $this->centerX = $this->lonToTile($this->lon, $this->zoom); - $this->centerY = $this->latToTile($this->lat, $this->zoom); - $this->offsetX = floor((floor($this->centerX)-$this->centerX)*$this->tileSize); - $this->offsetY = floor((floor($this->centerY)-$this->centerY)*$this->tileSize); - } - - public function createBaseMap(){ - $this->image = imagecreatetruecolor($this->width, $this->height); - $startX = floor($this->centerX-($this->width/$this->tileSize)/2); - $startY = floor($this->centerY-($this->height/$this->tileSize)/2); - $endX = ceil($this->centerX+($this->width/$this->tileSize)/2); - $endY = ceil($this->centerY+($this->height/$this->tileSize)/2); - $this->offsetX = -floor(($this->centerX-floor($this->centerX))*$this->tileSize); - $this->offsetY = -floor(($this->centerY-floor($this->centerY))*$this->tileSize); - $this->offsetX += floor($this->width/2); - $this->offsetY += floor($this->height/2); - $this->offsetX += floor($startX-floor($this->centerX))*$this->tileSize; - $this->offsetY += floor($startY-floor($this->centerY))*$this->tileSize; - - for($x=$startX; $x<=$endX; $x++){ - for($y=$startY; $y<=$endY; $y++){ - $url = str_replace(array('{Z}','{X}','{Y}'),array($this->zoom, $x, $y), $this->tileSrcUrl[$this->maptype]); - $tileImage = imagecreatefromstring($this->fetchTile($url)); - $destX = ($x-$startX)*$this->tileSize+$this->offsetX; - $destY = ($y-$startY)*$this->tileSize+$this->offsetY; - imagecopy($this->image, $tileImage, $destX, $destY, 0, 0, $this->tileSize, $this->tileSize); - } - } - } - - - public function placeMarkers(){ - foreach($this->markers as $marker){ - $markerLat = $marker['lat']; - $markerLon = $marker['lon']; - $markerImage = $marker['image']; - $markerIndex++; - $markerFilename = $markerImage?(file_exists($this->markerBaseDir.'/'.$markerImage.".png")?$markerImage:'lightblue'.$markerIndex):'lightblue'.$markerIndex; - if(file_exists($this->markerBaseDir.'/'.$markerFilename.".png")){ - $markerImg = imagecreatefrompng($this->markerBaseDir.'/'.$markerFilename.".png"); - } else { - $markerImg = imagecreatefrompng($this->markerBaseDir.'/lightblue1.png'); - } - $destX = floor(($this->width/2)-$this->tileSize*($this->centerX-$this->lonToTile($markerLon, $this->zoom))); - $destY = floor(($this->height/2)-$this->tileSize*($this->centerY-$this->latToTile($markerLat, $this->zoom))); - $destY = $destY - imagesy($markerImg); - - imagecopy($this->image, $markerImg, $destX, $destY, 0, 0, imagesx($markerImg), imagesy($markerImg)); - - }; -} - - - - public function tileUrlToFilename($url){ - return $this->tileCacheBaseDir."/".str_replace(array('http://'),'',$url); - } - - public function checkTileCache($url){ - $filename = $this->tileUrlToFilename($url); - if(file_exists($filename)){ - return file_get_contents($filename); - } - } - - public function checkMapCache(){ - $this->mapCacheID = md5($this->serializeParams()); - $filename = $this->mapCacheIDToFilename(); - if(file_exists($filename)) return true; - } - - public function serializeParams(){ - return join("&",array($this->zoom,$this->lat,$this->lon,$this->width,$this->height, serialize($this->markers),$this->maptype)); - } - - public function mapCacheIDToFilename(){ - if(!$this->mapCacheFile){ - $this->mapCacheFile = $this->mapCacheBaseDir."/".substr($this->mapCacheID,0,2)."/".substr($this->mapCacheID,2,2)."/".substr($this->mapCacheID,4); - } - return $this->mapCacheFile.".".$this->mapCacheExtension; - } - - - - public function mkdir_recursive($pathname, $mode){ - return mkdir($pathname, $mode, true); - } - public function writeTileToCache($url, $data){ - $filename = $this->tileUrlToFilename($url); - $this->mkdir_recursive(dirname($filename),0777); - file_put_contents($filename, $data); - } - - public function fetchTile($url){ - if($this->useTileCache && ($cached = $this->checkTileCache($url))) return $cached; - $ch = curl_init(); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0"); - curl_setopt($ch, CURLOPT_URL, $url); - $tile = curl_exec($ch); - curl_close($ch); - if($this->useTileCache){ - $this->writeTileToCache($url,$tile); - } - return $tile; - - } - - public function copyrightNotice(){ - $logoImg = imagecreatefrompng($this->osmLogo); - imagecopy($this->image, $logoImg, imagesx($this->image)-imagesx($logoImg), imagesy($this->image)-imagesy($logoImg), 0, 0, imagesx($logoImg), imagesy($logoImg)); - - } - - public function sendHeader(){ - header('Content-Type: image/png'); - $expires = 60*60*24*14; - header("Pragma: public"); - header("Cache-Control: maxage=".$expires); - header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT'); - } - - public function makeMap(){ - $this->initCoords(); - $this->createBaseMap(); - if(count($this->markers))$this->placeMarkers(); - if($this->osmLogo) $this->copyrightNotice(); - } - - public function showMap(){ - $this->parseParams(); - if($this->useMapCache){ - // use map cache, so check cache for map - if(!$this->checkMapCache()){ - // map is not in cache, needs to be build - $this->makeMap(); - $this->mkdir_recursive(dirname($this->mapCacheIDToFilename()),0777); - imagepng($this->image,$this->mapCacheIDToFilename(),9); - $this->sendHeader(); - if(file_exists($this->mapCacheIDToFilename())){ - return file_get_contents($this->mapCacheIDToFilename()); - } else { - return imagepng($this->image); - } - } else { - // map is in cache - $this->sendHeader(); - return file_get_contents($this->mapCacheIDToFilename()); - } - - } else { - // no cache, make map, send headers and deliver png - $this->makeMap(); - $this->sendHeader(); - return imagepng($this->image); - - } - } - -} - -$map = new staticMapLite(); -print $map->showMap(); - -?> - --- a/busui/stop.php +++ /dev/null @@ -1,23 +1,1 @@ -

'.staticmap(Array(0 => Array($stop[2],$stop[3]))).'

'; -echo ' '; -include_footer(); -?> - --- a/busui/stopList.php +++ /dev/null @@ -1,36 +1,1 @@ - - - - '; -echo '