Leaflet is an open source JavaScript library used to build web mapping applications. Capital MetroRail is a hybrid rail system that serves the Greater Austin area. In this talk we'll use Leaflet JS to show the 32-mile route of Capital MetroRail, where it's stops are and we'll use Leaftlet JS to provide real time tracking of the all the active rail cars on the network. We'll then use Leaflet JS to show the full 154-miles of train track that that Capital Metro owns (despite not operating trains on all of it), the counties that those 154-miles of track run through and what the route looked like in the 1950's as captured by Sanborn Fire Insurance Maps.
Our journey will take us from client-side Javascript and server-side PHP to the CLI and the database.
2. Jim Wigginton
• Creator and maintainer of phpseclib/phpseclib library
• PHP for ~20 years
• Born and raised in Austin, TX
• terrafrost@php.net
3.
4. Leaflet Setup
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js"></script>
<style>
body {
margin: 0;
}
</style>
<div id="map" style="width: 100%; height: 100%"></div>
<script>
var map = L.map('map').setView([51.505, -0.09], 13);
var tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
</script>
• The above is based off of https://leafletjs.com/examples/quick-start/
• [51.505, -09] is the latitude / longitude, 13 is the zoom
• Current location can be obtained by doing this:
• Real time location updates can be obtained by doing this:
navigator.geolocation.getCurrentPosition(pos => {
map.setView([pos.coords.latitude, pos.coords.longitude], 14);
});
navigator.geolocation.watchPosition(pos => {
polyline.addLatLng([pos.coords.latitude, pos.coords.longitude]);
});
6. Database Setup
1. Install the necessary software:
• Windows: Install OSGeo4W and then open "OSGeo4W Shell".
• Ubuntu: Run the following commands:
2. Download shapefiles from https://www.capmetro.org/metrolabs. Sort by "Recently Updated“
3. Import Routes.shp into MySQL:
sudo add-apt-repository ppa:ubuntugis/ppa
sudo apt-get update
sudo apt-get install gdal-bin
sudo apt-get install libgdal-dev
ogr2ogr -f MySQL MySQL:dbname,host=localhost,user=user,password=pass
Routes.shp -nln tablename -update -append
-t_srs "EPSG:4326" -lco engine=InnoDB -skipfailures
7. Coordinate Systems
Coordinate System Austin, TX Example
EPSG:4326 WGS 84 30.267222, -97.743056 TxDOT
EPSG:4269 NAD83 30.260336, -97.7458308 NHD, TIGER
EPSG:3857 WGS 84 / Pseudo-Mercator 3537945.1867267964, -10880707.234867256 US DOT
EPSG:3081 NAD83 / Texas State Mapping System 902702.814304697, 1216728.9256139707 THC
EPSG:32614 WGS 84 / UTM zone 14N 3349064.8428058745, 620908.0252681801 CapMetro
Conversions done with https://epsg.io/transform
8. Database
OGR_FID SHAPE route_id routename direction routecolor textcolor routetype routetheme servicenm servicetyp sign_id service_id source sourcedate
1 BLOB 1
North Lamar/South
Congress
Southbound 004A97 FFFFFF Local NULL Weekday Weekday 153 1-153
Capital
Metro
6/3/2022
2 BLOB 324 Georgian/Ohlen Westbound 004A97 FFFFFF Crosstown NULL Sunday Sunday 153 5-153
Capital
Metro
6/3/2022
3 BLOB 19 Bull Creek Northbound 004A97 FFFFFF Local NULL Sunday Sunday 153 5-153
Capital
Metro
6/3/2022
4 BLOB 243 Wells Branch Westbound 004A97 FFFFFF Feeder NULL Sunday Sunday 153 5-153
Capital
Metro
6/3/2022
5 BLOB 6 East 12th Westbound 004A97 FFFFFF Local NULL Saturday Saturday 153 4-153
Capital
Metro
6/3/2022
6 BLOB 310 Parker/Wickersham Eastbound 004A97 FFFFFF Crosstown NULL Weekday Weekday 153 1-153
Capital
Metro
6/3/2022
7 BLOB 339 Tuscany Westbound 004A97 FFFFFF Crosstown NULL Saturday Saturday 153 4-153
Capital
Metro
6/3/2022
8 BLOB 243 Wells Branch Eastbound 004A97 FFFFFF Feeder NULL Weekday Weekday 153 1-153
Capital
Metro
6/3/2022
9 BLOB 322 Chicon/Cherrywood Southbound 004A97 FFFFFF Crosstown NULL Sunday Sunday 153 5-153
Capital
Metro
6/3/2022
10 BLOB 550 Metro Rail Red Line Northbound E2231A FFFFFF Rail NULL RAIL AFC 2 Other 153 55004-153
Capital
Metro
6/3/2022
9. GeoJSON
1. Export from the DB with this SQL:
2. Load the GeoJSON in Leaflet by doing this:
SELECT ST_AsGeoJSON(SHAPE), servicenm, servicetyp
FROM capmetro_routes
WHERE route_id = 550
AND servicenm = '6TRAINMON to THURS';
L.geoJSON(route).addTo(map);
11. Markers
1. Export from the DB with this SQL:
2. Load the GeoJSON in Leaflet by doing this:
SELECT
stop_name,
CONCAT(latitude, ',', longitude) AS pos
FROM capmetro_stops
WHERE stop_type = 'Rail Station';
L.marker([30.264843,-97.738448])
.bindPopup('Downtown Station’)
.addTo(map);
12. GTFS Realtime
• General Transit Feed Specification
• Developed by Google in 2006
• Uses Protocol Buffers
• Get the download link for "CapMetro Vehicle Positions PB File"
from https://www.capmetro.org/metrolabs. Sort by "Recently Updated"
• Updated every 15s
• composer require google/gtfs-realtime-bindings
• Deprecated: As of February 2019, the official google-protobuf
Google protoc tool doesn’t support proto2 files. As a result we are
deprecating the PHP bindings until official support for proto2 files is
implemented in the Google protocol buffer tools.
13. GTFS Realtime: Server Side
<?php
require_once 'vendor/autoload.php’;
use transit_realtimeFeedMessage;
$output = [];
$data = file_get_contents('https://data.texas.gov/download/eiei-9rpf/application%2Foctet-stream’);
$feed = new FeedMessage();
$feed->parse($data);
foreach ($feed->getEntityList() as $entity) {
if ($entity->vehicle->trip && $entity->vehicle->trip->route_id == 550) {
$pos = $entity->vehicle->position; $output[] = [
'latitude' => $pos->latitude,
'longitude' => $pos->longitude,
'bearing' => $pos->bearing,
'speed' => $pos->speed
];
}
}
echo json_encode($output);
15. Putting It Together
• arrow-up.svg is from Font Awesome ( ) and was
edited with Inkscape
• https://github.com/bbecquet/Leaflet.RotatedMar
ker is used to rotate the arrow
• NYC: https://api.mta.info/
• Los Angeles: https://developer.metro.net/api/
• Chicago: https://www.transitchicago.com/developers/bustracker/
• Houston: https://api-portal.ridemetro.org/
• London: https://api.tfl.gov.uk/
• France: https://prim.iledefrance-mobilites.fr/fr
16. Austin Western Railroad
• Download and import shapefile from https://hub.arcgis.com/datasets/fedmaps::north-american-rail-
lines-1/explore
• Query:
SELECT *
FROM trains
WHERE rrowner1 = 'AWRR';
OGR_FID SHAPE objectid fraarcid frfranode tofranode cntyfips stateab country rrowner1 trkrghts1 subdiv passngr tracks net miles km shape_leng
123293 BLOB 123293 423812 360530 360533 287 TX US AWRR NULL
GIDDINGS
INDUSTRIA
L SPUR
NULL 1 I 0.040001 0.064375 0.000666
123294 BLOB 123294 423813 360533 360541 287 TX US AWRR NULL
GIDDINGS
INDUSTRIA
L SPUR
NULL 1 I 0.144155 0.231995 0.002261
123386 BLOB 123386 423905 355408 355502 453 TX US AWRR CMRX CENTRAL C 1 M 1.476048 2.375474 0.023111
123413 BLOB 123413 423932 355403 355406 453 TX US AWRR NULL NULL NULL 1 M 0.334526 0.538368 0.004952
123604 BLOB 123604 424123 353382 353376 53 TX US AWRR NULL MAIN LINE NULL 0 O 0.350358 0.563848 0.005183
123705 BLOB 123705 424224 358097 358085 21 TX US AWRR NULL NULL NULL 0 O 0.143777 0.231386 0.002201
123706 BLOB 123706 424225 358629 358637 21 TX US AWRR NULL NULL NULL 0 O 0.073028 0.117527 0.001145
123707 BLOB 123707 424226 358637 358651 21 TX US AWRR NULL NULL NULL 0 O 0.223662 0.35995 0.003704
123708 BLOB 123708 424227 358637 358648 21 TX US AWRR NULL NULL NULL 0 O 0.194351 0.312778 0.003207
124262 BLOB 124262 424783 355418 355416 453 TX US AWRR NULL NULL NULL 1 M 0.204555 0.329199 0.003038
39. Merging Overlapping GeoTIFFs
• Perform the merge:
• "In areas of overlap, the last image will be copied over earlier ones"
• Copy nextPage.tif as a new layer over temp.tif and trim away at nextPage.tif
• Copy the trimmed layer back to nextPage.tif, delete the old layer, and save as new.tif.
GeoTIFF data will be lost.
gdal_merge -o temp.tif nextPage.tif prevPage.tif
42. Tile Layer Caveats
"OSM does NOT pre-render every tile. Pre-rendering all tiles would use around 54
TB of storage. As the following table shows, the majority of tiles are never viewed.
In fact just 1.79% are viewed. It works out this way because the majority of tiles
are at zoom level 18 and actually the majority contain nothing of interest. By
following an on-the-fly rendering approach we can avoid rendering these tiles
unnecessarily. The tile view count column shows how many tiles have been
produced on the OSM Tile server."
Source: https://wiki.openstreetmap.org/wiki/Tile_disk_usage