Custom Points in OSW
Custom Points in OSW⚓︎
This guide shows how to add custom non-routable point features (like bus stops) to an OpenSidewalks dataset using the Custom Points entity type.
For a list of all guides on the TCAT Wiki, refer to the Guides List.
What are Custom Points?⚓︎
Custom Points in OpenSidewalks are user-defined non-routable point features that extend the schema beyond the predefined Core Entities and Adjacent Entities point types. While OpenSidewalks includes many built-in point types like fire hydrants, benches, and street lamps, Custom Points let you add any custom feature!
Doing so is simple - just prefix ext: before the tags that are not in the OSW schema.
This approach allows for immediately adding custom data, preserving data from existing systems.
Common Use Cases⚓︎
Custom Points are perfect for adding:
- Transit infrastructure: Bus stops, public transport shelters
- Accessibility features: Accessible parking spaces, wheelchair-accessible entrances, elevators
- Wayfinding aids: Information kiosks, signage
- Points of interest: Water fountains, ATMs, restrooms
Case Study: GTFS Bus Stops to OSW Custom Points⚓︎
In this example, we'll convert bus stop data from a GTFS stops.txt file into OpenSidewalks Custom Points. This is a common scenario for transit agencies and cities wanting to integrate public transportation data with pedestrian network information.
Understanding the Source Data⚓︎
A typical GTFS stops.txt file contains bus stop information like this:
stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,zone_id,stop_url,location_type,parent_station
1001,1001,Main St & 1st Ave,Northbound stop,47.6062,-122.3321,,http://example.com/stops/1001,0,
1002,1002,Main St & 2nd Ave,Southbound stop,47.6065,-122.3325,,http://example.com/stops/1002,0,
The Target: OSW Custom Points⚓︎
We want to convert each bus stop into an OpenSidewalks Custom Point that looks like this:
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-122.3321, 47.6062]
},
"properties": {
"_id": "bus_stop_1001",
"ext:stop_id": "1001",
"ext:stop_code": "1001",
"ext:stop_name": "Main St & 1st Ave",
"ext:stop_desc": "Northbound stop",
"ext:stop_url": "http://example.com/stops/1001"
}
}
Step-by-Step Conversion Process⚓︎
Step 1: Prepare Your Data⚓︎
Start with your GTFS stops.txt file. You'll need these key fields:
stop_latandstop_lon(for coordinates)stop_id(for unique identification)- Any other fields you want to preserve (name, description, etc.)
Quality check your data:
- Remove any stops with missing coordinates
- Ensure stop_id values are unique
- Verify coordinates are in decimal degrees (WGS84)
Step 2: Map Fields to OSW Structure⚓︎
Create a mapping between your GTFS fields and OSW Custom Point properties:
| GTFS Field | Goes in OSW as | Notes |
|---|---|---|
stop_lon, stop_lat |
geometry.coordinates |
Longitude first, then latitude |
stop_id |
_id |
Create unique OSW ID (e.g., "bus_stop_" + stop_id) |
stop_id |
ext:stop_id |
Keep original ID for reference |
stop_name |
ext:stop_name |
Preserve original name |
stop_desc |
ext:stop_desc |
Optional description |
stop_code |
ext:stop_code |
Display code, if different from ID |
stop_url |
ext:stop_url |
Link to more information |
A note on the _id field: Every OSW entity needs a unique _id (string with at least one character). For bus stops, consider using a prefix like "bus_stop_" + the original stop_id to avoid conflicts with other features. Letters, numbers, and underscores are all fine!
Step 3: Create the GeoJSON Structure⚓︎
- Required fields like
_idgo directly inproperties - Custom fields get the
ext:prefix and go inproperties - Geometry goes in the
geometrysection, notproperties
Your Custom Points need to be formatted as GeoJSON Features within a FeatureCollection. Here's how the field mapping from Step 2 translates into actual JSON:
{
"$schema": "https://sidewalks.washington.edu/opensidewalks/0.3/schema.json",
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-122.3321, 47.6062] // stop_lon, stop_lat
},
"properties": {
"_id": "bus_stop_1001", // Required OSW field
"ext:stop_id": "1001", // Original GTFS stop_id
"ext:stop_name": "Main St & 1st Ave", // Original GTFS stop_name
"ext:stop_desc": "Northbound stop" // Original GTFS stop_desc
}
}
]
}
Key Structure Points:
- All of the GTFS data fields (except coordinates) go in the
propertiessection - Custom fields like
ext:stop_nameare the actual field names in your JSON - The
ext:prefix is part of the field name, not a folder structure
Step 4: Add Dataset Metadata⚓︎
Include required OpenSidewalks metadata at the dataset level:
{
"$schema": "https://sidewalks.washington.edu/opensidewalks/0.3/schema.json",
"type": "FeatureCollection",
"dataSource": {
"name": "Metro Transit GTFS",
"license": "Public Domain"
},
"dataTimestamp": "2024-12-01T00:00:00Z",
"features": [
// ... your custom points here
]
}
Conversion Tools⚓︎
Option 1: Purpose-built Scripts⚓︎
In the specific case of GTFS stops, a script such as this one created by TCAT, gtfs-to-tdei-converter.ps1, can be used.
Option 2: Online JSON Tools⚓︎
Use your spreadsheet software of choice to add ext: prefix to column headers, then convert CSV to GeoJSON:
- https://geojson.io/
- https://mapbox.github.io/csv2geojson/
Validation and Quality Assurance⚓︎
Check Your Output⚓︎
Before using your Custom Points, verify:
- Valid GeoJSON: Use geojson.io or a JSON validator
- Coordinate format: Longitude first, then latitude
- Unique IDs: Each
_idappears only once - Required fields: Every Custom Point has an
_idand valid coordinates - Custom fields: All additional data uses the
ext:prefix
Common Issues and Fixes⚓︎
| Problem | Solution |
|---|---|
| Coordinates reversed | Longitude should be first: [lng, lat] |
Missing _id field |
Add unique identifier to each feature |
| Invalid JSON | Use a JSON validator to find syntax errors |
| Coordinate precision | GTFS uses 6+ decimal places; preserve precision |
Integration with Existing OSW Data⚓︎
Manual Adding to Existing Datasets⚓︎
To add Custom Points to an existing OpenSidewalks dataset:
- Load your existing .osw file
- Add your Custom Point features to the
featuresarray - Ensure all
_idvalues remain unique across the entire dataset
Coordinate System Compatibility⚓︎
OpenSidewalks uses WGS84 (EPSG:4326) coordinates in decimal degrees. GTFS data is already in this format, so no conversion is needed. If your source data uses a different coordinate system, you'll need to reproject it first.
Best Practices⚓︎
Fields⚓︎
- Use descriptive
ext:field names:ext:stop_namenotext:name - Keep original field names when possible for easier maintenance
- Be consistent across all your Custom Points
- Remove unnecessary fields to keep file sizes manageable