[
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2017 SharedStreets\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "OSMLR.md",
    "content": "### OSMLR and SharedStreets\n\nOSMLR v1.x was developed to support OpenTraffic under contract from the World Bank. SharedStreets is the continuation of this work as part of the Open Transport Partnership. The SharedStreets Referencing system is effectively \"OSMLR v2.0\" but drops the OSMLR name as it intends to support broad range of map data formats including, but not limited to, OpenStreetMap. \n\nSharedStreets also addresses two problems in the OSMLR v1.x implementation:\n\n**1) OSMLR v1.x segment references over 1km in length are unstable.**\n\nThe OSMLR v1.x implementation splits street segments into 1km sections. This design conflates location referencing (the identification of street segments) with linear reference (the identification of locations along segments).\n\nAs segment geometries change due to improved mapping, the length of segments changes, sometimes substantially. For longer segments this could create or destroy OSMLR references (e.g. a 10km stretch of road becomes 12km when the map is improved, resulting in two new OSMLR 1km segments). This undermines one the of the core ideas of OpenLR: underlying map geometries can change while segment references remain stable.\n\n\n![GIS vs SharedStreets Geometries](img/sharedstreets_osmlr_stability.png)\n\nThis problem is especially serious in developing countries where the quality of maps are rapidly improving. It also creates problems sharing data between users with different quality basemaps. Users with more precise maps will in most cases have longer street segments, resulting in new OSMLR segments that cannot be generated by users with coarser maps.\n\nPre-spliting segments into 1km sections also undermines applications that describe locations along segments (e.g curbside parking regulations) or features that span longer sections of road. Given the geometry changes may move (or even create or destroy) segment references, precise/stable linear referencing is not possible using OSMLR v1.x.\n\nSharedStreets addresses this problem by decoupling location referencing and linear reference. All streets segments are mapped at intersection to intersection. Users with different quality maps should be able to overcome variations in geometry length by using other properties of the reference (segment end points, bearing, and \"form of way\") to match segments. SharedStreets provides a separate linear referencing format to describe points or sections of the segment.\n\n**2) OSMLR shorthand IDs can't be reproduced without use of specialized software. This undermines OSMLR's value as a universal, non-proprietary standard.**\n\nThe OSMLR 1.x implementation depends on Valhalla routing engine to generate segment IDs. These IDs cannot be generated without deploying the Valhalla system. This creates a dependency on a specific piece of software, likely reducing the value of the OSMLR spec by non-Valhalla users.\n\nSharedStreets addresses this by creating a deterministic, software-independent process for generating shorthand IDs. SharedStreets provides open source software as a reference, but the methods can be easily incorporated into other applications to independently generate matching IDs.\n\nThe above issues noted, OSMLR v1.x can be mapped to SharedStreets segments when needed. SharedStreets segments cannot be accurately described using OSMLR v1.x due to limitations of the OSMLR v1.x spec.\n"
  },
  {
    "path": "README.md",
    "content": "# SharedStreets Referencing System\n\n## Introduction\n\nSharedStreets data standards are a way to uniquely identify street space and connect data related to streets. SharedStreets makes maps connectable, and allows porting of data between different street representations, whether data linked to OpenStreetMap, a city-managed GIS system, or a commercial basemap.\n\nCities today depend on geographic information systems (GIS) to collect and share street data, but this process requires users to agree on a map, or to use predefined, and often proprietary IDs to describe streets.\n\nThis limits the potential for collaboration and data sharing between government agencies, and with the private sector. And use of proprietary maps and identification systems can undermine cities’ ability to use and share critical public information about streets.\n\nSharedStreets provides a global, non-proprietary system for describing streets, designed to incorporate any source of street-linked data. This allows public and private entities to communicate with clarity and precision about streets while ensuring full compatibility with organizations’ internal map data.\n\n![GIS vs SharedStreets data exchange](img/gis_vs_sharedstreets.png)\n\nThe SharedStreets referencing system was originally created as part of the [OpenTraffic project](https://github.com/opentraffic/architecture/issues/1), as a mechanism for sharing dynamic traffic information. SharedStreets builds on the core concepts from [OpenLR](http://www.openlr.info/) and provides a collection of data formats and open source tools to re-imagine collaboration and sharing of street-linked data.\n\nThe SharedStreets referencing system is being released as a draft proposal, along with data samples and tools for generating references from OpenStreetMap and Shapefile data sources. Comments and suggestions on the format will be managed via this Github repository. Please open an Github issue or pull request to contribute.\n\n**A production version of the SharedStreets Referencing System and a global data set will be released soon. During the preview phase, referencing data can be generated using open source tools for any location.**\n\n### Example Applications\n\n**Traffic data:** SharedStreets references are used to share basemap-independent descriptions of traffic conditions. In the OpenTraffic project fleet operators convert GPS data to to traffic observations (speeds along OpenStreetMap defined roadway segments). Traffic observations are shared externally using SharedStreets references to describe street segments.\n\n**Street and curb inventory:** Cities produce detailed curb inventories (e.g. parking regulations and physical assets) using internally managed linear referencing systems (LRS), or latitude/longitude coordinates not linked with streets. Internal LRS data can be translated to SharedStreets references to allow interoperability with other city or external data sets.\n\n**Incident/road closure reporting:** transport authorities share data about street conditions in real-time with consumer applications. SharedStreets references can be used to streamline reporting procedures by providing a shared, non-proprietary format for describing roadway incidents and closure events.\n\n## Core Concepts\n\nThe SharedStreets Referencing system is built on four layers of data:\n\n1. **SharedStreets References:** basemap-independent references for intersection to intersection street segments\n2. **SharedStreets Intersection:** nodes connecting street street segments references\n3. **SharedStreets Geometries:** geometries used to generate street segment references\n4. **OSM Metadata:** underlying OSM way and node references used to construct SharedStreets data\n\n### Segment references\n\nThe OpenLR-style street segment references are the foundation of the SharedStreets Referencing System. These references allow users to uniquely describe any street segment in the world using just a few high-level characteristics.\n\nThis allows users with different map geometries to describe the same street segments in identical or nearly identical terms. The references are used to find matching streets in users' existing internal maps. In cases where no matching street is found, users have the opportunity to update their map data to fill in missing or incorrectly mapped segments.\n\nStreet segment references protect users' intellectual property, as data can be shared without disclosing a complete map. Segment references also enable rapid reconciliation of data derived from different maps.\n\n### BYOM\nSharedStreets is based on the idea that users will maintain their own internal basemaps. Any basemap--open or proprietary--can generate SharedStreets references for sharing with others using a different map. With open basemap data users are encouraged to share the full set of SharedStreets data layers (references, geometries and metadata). Users with proprietary basemap data can share only the segment references, allowing exchange of information while protecting map street geometries and other intellectual property.\n\n### Stable, non-proprietary shorthand IDs\nSharedStreets uses 128-bit shorthand identifiers to relate data within the SharedStreets referencing system. These IDs provide a basemap-independent addressing system for street segment references, intersections and geometries. **These identifiers are generated deterministically using a hash of the underlying data.** This means that two different users with the same input data can generate matching SharedStreets identifiers. This simplifies data sharing, allowing users to match data using shorthand IDs whenever possible.\n\nIn the draft specification the 128-bit IDs are encoded as base-16 (hex) strings.\n\n### Generating references + data tiles\nSharedStreets street references, intersections and geometries can be generated from OSM data using the [SharedStreets Builder](https://github.com/sharedstreets/sharedstreets-builder) application.\n\nAs part of the draft release pre-generated a sample of SharedStreets tiles for New York City are included in this repository. A zip archive of the full NYC tile set can be [downloaded here](https://www.dropbox.com/s/ys1wb25aipmkbi2/nyc_sample_data.zip?dl=0) (146MB file). Users can generate their own tiles for any arbitrary OSM data set using the SharedStreets Builder application.\n\nOnce the data specification is finalized the SharedStreets program will generate and maintain a global data tile set, and provide tools to cities for reconciling their data with the referencing system.\n\nThe draft release of SharedStreets exports data as JSON files, cut into mercator tiles at zoom level 10. These draft tiles are verbose and are designed to support exploration and refinement of the specification. Once the specification is finalized SharedStreets will provide JSON and Protocol Buffer tile formats. SharedStreets is also exploring use of \"lossy\" vector tile formats for distribution of data for web visualization.\n\n## DRAFT ShareStreets Data Formats\n\n### Changelog\n\n*2017-10-20:* Initial release for comments, using JSON tile representation.\n\n*2017-11-10:* Updated spec to include \"inbound\" and \"outbound\" bearings for references, backwards compatible with OpenLR-derived data standards while allowing for more complex geometry matching workflows. (Thanks to [@migurski](https://github.com/migurski) and [@remix](https://github.com/remix) for this suggestion.)\n\n*2017-11-20:* Switched from JSON to [protocol buffer encoded tiles](https://github.com/sharedstreets/sharedstreets-ref-system/blob/master/proto/sharedstreets.proto) as default output format.\n\n*2018-01-14:* Switched IDs to base-16 (hex) encoding. Release of updated sharedstreets-builder application (v0.1.2) and sample tile set.\n\n### Protocol Buffer Encoding\n\nSharedStreets encodes reference data in protocol buffer encoded map tiles. The encoding format, [described here](https://github.com/sharedstreets/sharedstreets-ref-system/blob/master/proto/sharedstreets.proto), targets the Protocol Buffer v3 format, and uses the following conventions to enable efficient data storage:\n\n- [\"Oneof\" wrappers](https://github.com/google/protobuf/issues/1606) allow null values for optional fields. This allows for space-efficient values, while ensuring that downstream users can differentiate between zero and null values for bearings and lengths.\n\n- Strings of latitude/longitude values for geometries are encoded as a single stream of values (e.g. \"[-74.003388, 40.634538],[-74.004107, 40.63406]\" is encoded as \"-74.003388,40.634538,-74.004107,40.63406\".\n\n- Distances are encoded in centimeters using int32 field types.\n\nFor more information about encoding see the [SharedStreets Builder](https://github.com/sharedstreets/sharedstreets-builder) application, which converts OpenStreetMap and other geospatial data into SharedStreets protocol buffer tiles.\n\n### SharedStreets Intersections\n\n![GIS vs SharedStreets data exchange](img/sharedstreets_intersections.png)\n\n```javascript\n{\n\t\"type\": \"Feature\",\n\t\"properties\": {\n\t\t\"id\": \"5gRJyF2MT5BBErTyEesQLC\",\n\t\t\"osmNodeId\": 42460951,\n\t\t\"outboundReferenceIds\": [\"6mjqqv7YNsp4541DmrrRbV\", \"jwwKcUvHuCw6GJJAT3mDQ\", \"2Vw2XzW4cs7r32RLhQnqwA\"],\n\t\t\"inboundReferenceIds\": [\"VmSkhzGKoEc767w98x35La\", \"VXKSEokmvBJ81XHYhUronG\", \"B7RPzs3hb1cSXqYcAKmUhE\"]\n\t},\n\t\"geometry\": {\n\t\t\"type\": \"Point\",\n\t\t\"coordinates\": [-74.003388, 40.634538]\n\t}\n}\n```\n\n```javascript\n{\n\t\"type\": \"Feature\",\n\t\"properties\": {\n\t\t\"id\": \"N38a21UGykpnqxwez7NGS3\",\n\t\t\"osmNodeId\": 42460956,\n\t\t\"outboundReferenceIds\": [\"VXKSEokmvBJ81XHYhUronG\", \"KxeV6ycjnarJU8pGEmkUx9\", \"V6aRcYcZgd5D58GaEaxCaF\"],\n\t\t\"inboundReferenceIds\": [\"8ShvkUbHhu1SXzcE5XMj2L\", \"Ak3c8QdsYWVRn5Ap53hzcH\", \"2Vw2XzW4cs7r32RLhQnqwA\"]\n\t},\n\t\"geometry\": {\n\t\t\"type\": \"Point\",\n\t\t\"coordinates\": [-74.004107, 40.63406]\n\t}\n}\n```\n\n### SharedStreets References\n\n![GIS vs SharedStreets data exchange](img/sharedstreets_references.png)\n\nSharedStreets References (SSR) are directional edges in a road network. Two-way streets have two SSRs, one for each direction of travel, while one-way streets only have one SSR. In the draft specification these are labeled \"forward references\" and \"back references,\" with the forward reference following the direction of the map geometry used to generate the references.\n\nEach SharedStreets Reference consists of two or more location references (LRs) that describe the latitude and longitude of the beginning or end of a street segment. SSRs also describe type of road (or the \"form of way,\" as defined by OpenLR), and length of the geometry connecting location reference points. In combination these attributes uniquely describe any road segment, and can be used to look up corresponding streets in users’ internal maps.\n\n#### Forward Reference\n\n```javascript\n{\n\t\"id\": \"2Vw2XzW4cs7r32RLhQnqwA\",\n\t\"geometryId\": \"NxPFkg4CrzHeFhwV7Uiq7K\",\n\t\"formOfWay\": 3,\n\t\"locationReferences\": [{\n\t\t\"sequence\": 1,\n\t\t\"point\": [-74.003388, 40.634538],\n\t\t\"bearing\": 228.890377,\n\t\t\"distanceToNextRef\": 80.730221,\n\t\t\"intersectionId\": \"5gRJyF2MT5BBErTyEesQLC\"\n\t}, {\n\t\t\"sequence\": 2,\n\t\t\"point\": [-74.004107, 40.63406],\n\t\t\"intersectionId\": \"N38a21UGykpnqxwez7NGS3\"\n\t}]\n}\n```\n\n#### Back Reference\n\n```javascript\n{\n\t\"id\": \"VXKSEokmvBJ81XHYhUronG\",\n\t\"geometryId\": \"NxPFkg4CrzHeFhwV7Uiq7K\",\n\t\"formOfWay\": 3,\n\t\"locationReferences\": [{\n\t\t\"sequence\": 1,\n\t\t\"point\": [-74.004107, 40.63406],\n\t\t\"bearing\": 48.890138,\n\t\t\"distanceToNextRef\": 80.730221,\n\t\t\"intersectionId\": \"N38a21UGykpnqxwez7NGS3\"\n\t}, {\n\t\t\"sequence\": 2,\n\t\t\"point\": [-74.003388, 40.634538],\n\t\t\"intersectionId\": \"5gRJyF2MT5BBErTyEesQLC\"\n\t}]\n}\n```\n\n*Notes:*\n\n- For long segments LRs are repeated every 15km, segments shorter than 15km have only a beginning and end LR.\n- LRs describe the compass bearing of the street geometry for the 20 meters immediately following the LR. The final LR of a SSR does not provide a bearing.\n- An initial set of SSRs are built using OpenStreetMap (OSM) data, however, in the future SharedStreets users will be able to publicly register SSRs for streets not found in OSM. These could include data found in commercial or government maintained basemaps. Users do not have to share the underlying data, only the SSR descriptor.\n\n### SharedStreets Geometries\n\n![GIS vs SharedStreets Geometries](img/sharedstreets_geometries.png)\n\n\nSharedStreets Geometries are street centerline data derived from the basemap used to produce SharedStreets References. A single geometry is shared by each set of forward and back references.\n\nSharedStreets is premised on the idea that there's no one correct geometry for a given street. Just as street references can be generated from any basemap, street geometries can be derived from any data source.\n\n```javascript\n{\n\t\"type\": \"Feature\",\n\t\"properties\": {\n\t\t\"id\": \"NxPFkg4CrzHeFhwV7Uiq7K\",\n\t\t\"fromIntersectionId\": \"5gRJyF2MT5BBErTyEesQLC\",\n\t\t\"toIntersectionId\": \"N38a21UGykpnqxwez7NGS3\",\n\t\t\"forwardReferenceId\": \"2Vw2XzW4cs7r32RLhQnqwA\",\n\t\t\"backReferenceId\": \"VXKSEokmvBJ81XHYhUronG\",\n\t\t\"roadClass\": 3\n\t},\n\t\"geometry\": {\n\t\t\"type\": \"LineString\",\n\t\t\"coordinates\": [\n\t\t\t[-74.003388, 40.634538],\n\t\t\t[-74.003621, 40.634383],\n\t\t\t[-74.003621, 40.634383],\n\t\t\t[-74.004107, 40.63406]\n\t\t]\n\t}\n}\n```\n\n### SharedStreets OSM Metadata\n\nSharedStreets generates metadata about the map data used to generate references and geometries. For OSM-derived references the way and nodes are stored as part of metadata layer. This simplifies matching references back to underlying basemap data, and provides a framework to easily track changes in the underlying basemap data.\n\n```javascript\n{\n\t\"geometryId\": \"NxPFkg4CrzHeFhwV7Uiq7K\",\n\t\"waySections\": [{\n\t\t\"wayId\": 420584810,\n\t\t\"roadClass\": 3,\n\t\t\"oneWay\": false,\n\t\t\"roundabout\": false,\n\t\t\"link\": false,\n\t\t\"nodeIds\": [42460951, 4205392123]\n\t}, {\n\t\t\"wayId\": 420584817,\n\t\t\"roadClass\": 3,\n\t\t\"oneWay\": false,\n\t\t\"roundabout\": false,\n\t\t\"link\": false,\n\t\t\"nodeIds\": [4205392123, 42460956]\n\t}]\n}\n```\n\n### Frequently Asked Questions\n\n#### How does this relate to OpenStreetMap? (Or, doesn't OSM already do this?)**\n\nSharedStreets complements OpenStreetMap. OSM does not attempt to provide stable IDs, and complex OSM ways make many applications difficult to build using raw OSM data.\n\nSharedStreets provides a layer of abstraction on top of OSM, allowing users to work with the *topology* of OpenStreetMaps data without dealing with the details how OSM ways are encoded.\n\nBy providing direct references to OSM way and node IDs users can always query and relate SharedStreets references back to the underlying OSM data where needed.\n\nWe believe that SharedStreets will allow users to more rapidly improve OpenStreetMap data by making it easier to identify missing streets, or opportunities to improve street geometry and connectivity.\n\n#### How does SharedStreets relate to OSMLR v1.x?\n\nOSMLR v1.x was developed to support OpenTraffic under contract from the World Bank. SharedStreets is the continuation of this work as part of the Open Transport Partnership. The SharedStreets Referencing system is effectively \"OSMLR v2.0\" but drops the OSMLR name as it intends to support broad range of map data formats including, but not limited to, OpenStreetMap. SharedStreets also addresses two critical deficiencies in the OSMLR v1.x spec, [documented here](https://github.com/sharedstreets/sharedstreets-ref-system/blob/master/OSMLR.md).\n"
  },
  {
    "path": "proto/linear_references.proto",
    "content": "syntax = \"proto3\";\n\noption java_outer_classname = \"SharedStreetsLinearReferencesProto\";\n\n\n// linear referencing spec for SharedStreets allows description of point and segments features along street references\n//\n//   [ SharedStreets Ref ]\n//   =============*=======\n//                ^ point at distance: 75 along reference\n//\n//   [ SharedStreets Ref ]\n//   ========*******======\n//           ^     ^ linear segment from distance 50 to 75 along SharedStreets reference\n\n\nmessage LinearReference {\n\n  uint64 startDistance = 1; // start distance along SharedStreets reference\n\n  oneof endDistance_present {\n    uint64 endDistance = 2;// end distance along SharedStreets reference, null for point linear references\n  }\n\n}\n\nmessage SharedStreetsLinearReferences {\n\n  string referenceId = 1; // SharedStreets Reference ID\n\n  uint64 referenceLength = 2; // total length of SharedStreets reference in centimeters (allows users to compare expected length with actual length in internal data)\n\n  repeated LinearReference references = 3; // one or more linear reference associated with a SharedStreets reference\n\n}\n\n// \"binned\" linear referencing spec for SharedStreets allows grouping of linear point features into segments along reference\n//\n//   [ SharedStreets Ref ]\n//   referenceLength = 100m\n//   numberOfBins = 5\n//   =====*=====*=====*=====*=====\n//     0     1     2     3     4   = bin position (20m/bin)\n//     4     8     0     2     0   = bin value (count of grouped linear features)\n//\n\nmessage DataBin {\n  repeated string dataType = 1;\n  repeated uint64 count = 2;\n  repeated double value = 3;\n}\n\nmessage BinnedPeriodicData {\n  repeated uint32 periodOffset  = 1; \n  repeated DataBin bins = 2;\n}\n\nmessage SharedStreetsBinnedLinearReferences {\n\n  string referenceId = 1;            // SharedStreets Reference ID\n  bool scaledCounts = 2;             // counts in histogram are stored as scaled numbers, otherwise stored as absolute counts\n  \n  uint64 referenceLength = 3;        // total length of SharedStreets reference in centimeters (allows users to compare expected length with actual length in internal data)\n  uint32 numberOfBins = 4;           // number of bins, bin size is referenceLength / numberOfBins\n                                   \n  repeated uint32  binPosition = 5;  // bin position offset (0 to n-1 bins)\n  repeated DataBin bins = 6;         // bin value ()\n\n}\n\nenum PeriodSize {\n    OneSecond = 0;\n    FiveSeconds = 1;\n    TenSeconds = 2;\n    FifteenSeconds = 3;\n    ThirtySeconds = 4;\n    OneMinute = 5;\n    FiveMinutes = 6;\n    TenMinutes = 7;\n    FifteenMinutes = 8;\n    ThirtyMinutes = 9;\n    OneHour = 10;\n    OneDay = 11;\n    OneWeek = 12;\n    OneMonth = 13;\n    OneYear = 14;\n}\n\nmessage SharedStreetsWeeklyBinnedLinearReferences {\n\n  string referenceId = 1;           // SharedStreets Reference ID\n  PeriodSize periodSize = 2;        // optional (hourly if ommited)\n\n  bool scaledCounts = 3;            // counts in histogram are stored as scaled numbers, otherwise stored as absolute counts\n  \n  uint64 referenceLength = 4;       // total length of SharedStreets reference in centimeters (allows users to compare expected length with actual length in internal data)\n  uint32 numberOfBins = 5;          // number of bins, bin size is referenceLength / numberOfBins\n                                    \n  repeated uint32   binPosition = 6;                   // period\n  repeated BinnedPeriodicData binnedPeriodicData = 7;  // bin value ()\n\n}\n"
  },
  {
    "path": "proto/sharedstreets.proto",
    "content": "syntax = \"proto3\";\n\noption java_outer_classname = \"SharedStreetsProto\";\n\nmessage Delimiter {\n  uint32 length = 1;\n}\n\nmessage GISSectionMetadata {\n  string sectionId = 1; // source specific id\n  string sectionProperties = 2; // source specific encoding of properties\n}\n\nmessage GISMetadata {\n  string source = 1; // describes GIS source data (e.g. \"gov.nyc:lion\")\n  repeated GISSectionMetadata sections = 2;\n}\n\nenum RoadClass {\n  Motorway = 0;\n  Trunk = 1;\n  Primary = 2;\n  Secondary = 3;\n  Tertiary = 4;\n  Residential = 5;\n  Unclassified = 6;\n  Service = 7;\n  Other = 8;\n}\n\nmessage WaySection {\n  uint64 wayId =1 ;\n\n  RoadClass roadClass = 2;\n\n  bool oneWay = 3;\n  bool roundabout = 4;\n  bool link = 5;\n  repeated uint64 nodeIds = 6;\n  \n  string name  = 7; // name only stored here if different for each way section, otherwise captured in OSMMetadata\n}\n\nmessage OSMMetadata {\n  repeated WaySection waySections = 1;\n  string name  = 2; // name stored here if same for all way sections\n}\n\nmessage SharedStreetsMetadata {\n  string geometryId = 1;\n\n  OSMMetadata osmMetadata = 2;\n  repeated GISMetadata gisMetadata = 3;\n}\n\nmessage SharedStreetsGeometry {\n  string id = 1;\n\n  string fromIntersectionId = 2;\n  string toIntersectionId = 3;\n  string forwardReferenceId = 4;\n  string backReferenceId = 5;\n\n  RoadClass roadClass = 6;\n  repeated double lonlats = 7; // interleaved lon/lat pairs in sequence\n}\n\nmessage LocationReference {\n  string intersectionId = 1;\n\n  double lon = 2;\n  double lat = 3;\n\n  oneof inboundBearing_present {\n    int32 inboundBearing = 4; // rounded to nearest degree 0-360 -- optional field, using proto3 oneof to allow for nulls\n  }\n\n  oneof outboundBearing_present {\n    int32 outboundBearing = 5; // rounded to nearest degree 0-360 -- optional field, using proto3 oneof to allow for nulls\n  }\n\n  oneof distanceToNextRef_present {\n    int32 distanceToNextRef = 6; // in centimeters -- max value of 15km -- optional field, using proto3 oneof to allow for nulls\n  }\n}\n\nmessage SharedStreetsReference {\n  string id = 1;\n  string geometryId = 2;\n\n  enum FormOfWay {\n    Undefined = 0;\n    Motorway = 1;\n    MultipleCarriageway = 2;\n    SingleCarriageway = 3;\n    Roundabout = 4;\n    TrafficSquare = 5; // yikes: https://giphy.com/gifs/square-addis-meskel-GYb9s3Afw0cWA\n    SlipRoad = 6;\n    Other = 7;\n  }\n  FormOfWay formOfWay = 3;\n\n  repeated LocationReference locationReferences = 4;\n}\n\nmessage SharedStreetsIntersection {\n  string id = 1;\n  uint64 nodeId = 2;\n  double lon = 3;\n  double lat = 4;\n\n  repeated string inboundReferenceIds = 5;\n  repeated string outboundReferenceIds = 6;\n}\n"
  },
  {
    "path": "proto/speeds.proto",
    "content": "syntax = \"proto3\";\n\noption java_outer_classname = \"SharedStreetsSpeedsProto\";\n\nenum PeriodSize {\n    OneSecond = 0;\n    FiveSeconds = 1;\n    TenSeconds = 2;\n    FifteenSeconds = 3;\n    ThirtySeconds = 4;\n    OneMinute = 5;\n    FiveMinutes = 6;\n    TenMinutes = 7;\n    FifteenMinutes = 8;\n    ThirtyMinutes = 9;\n    OneHour = 10;\n    OneDay = 11;\n    OneWeek = 12;\n    OneMonth = 13;\n    OneYear = 14;\n}\n\n// temporal references for SharedStreets events (in UTC)\n\nmessage TemporalPeriod {\n\n  PeriodSize periodSize = 1;\n  uint64 periodOffset = 2; // period offset from unix epoch\n                           // For periodSize = oneYear:\n                           //   1970-01-01 = 0\n                           //   2015-01-01 = 45\n                           // For periodSize = OneMonth:\n                           //   1970-01-01 = 0\n                           //   2015-01-01 = 540\n                           // For periodSize = OneSecond: periodOffset = UNIX timestamp\n\n}\n\n// template for storing weekly cycles of events in local time -- used as a template for developing application specific data standards\n// assumes Monday-Sunday week in local time. See OpenTraffic weekly speed data for example implementation.\nmessage WeeklyCycle {\n\n  uint32 year = 1;     // date for Monday of week (Monday midnight is zero for week cycle per ISO-8601)\n  uint32 month = 2;\n  uint32 day = 3;\n\n  PeriodSize periodSize = 4;\n\n  // repeated [...] periodData = ...; // replace with application specific data payload\n\n\n}\n\n// SharedStreets uses histograms to store speed observations\n// This allows aggregation and calculation of statistics from distribution of speeds\n//\n//   count\n//    4 |       *\n//    3 |     * *   * *\n//    2 |   * * * * * * *\n//    1 | * * * * * * * * * *\n//       ________________________\n//        0 1 2 3 4 5 6 7 8 9\n//             Speed (km/h)\n//\n//   Mean and variance can be calculated from distribution.\n//   Histograms with absolute counts can be added together to merge observations.\n//   Histograms can also be stored using scaled counts (0-100 default) to hide absolute observation counts\n\nmessage SpeedHistogram {\n    repeated uint32 speedBin = 1;         // repeated speed bins in km/h, bins are unordered and may not be sequential\n    repeated uint32 observationCount = 2; // number of observations for corresponding speedBin. Counts are repeated in same order as bins.\n}\n\nmessage SpeedHistogramByPeriod {\n    repeated uint32 periodOffset = 1;      // repeated offset for period (Monday, midnight is zero for week cycle per ISO-8601)\n    repeated SpeedHistogram histogram = 2; // SpeedHistogram for period\n}\n\nmessage SpeedSummary{\n    uint32 meanSpead = 1;                  // mean speed in km/h\n\n    repeated uint32 percentile = 2;        // repeated percentile value (e.g 50th, 85th stored as 50 or 85)\n    repeated uint32 observationCount = 3;  // km/h value for corresponding percentile\n}\n\nmessage SpeedSummaryByPeriod{\n    repeated uint32 periodOffset = 1;        // repeated offset for period (Monday, midnight is zero for week cycle per ISO-8601)\n    repeated SpeedSummary speedSummary = 3;  // SpeedSummary for period\n}\n\n\n// defines weekly speeds based on speed histogram and/or summary + linear binning following approach used in SharedStreetsBinnedLinearReferences\nmessage SharedStreetsWeeklySpeeds {\n\n  string referenceId = 1;                       // SharedStreets Reference ID\n  \n  PeriodSize periodSize = 2;                    // optional (hourly if ommited)\n\n  bool scaledCounts = 3;                        // counts in histogram are stored as scaled numbers, otherwise stored as absolute counts\n  \n  uint64 referenceLength = 4;                   // total length of SharedStreets reference in centimeters (allows users to compare expected length with actual length in internal data)\n  uint32 numberOfBins = 5;                      // number of linear bins. bin size is referenceLength / numberOfBins\n\n  repeated uint32 binPosition = 6;                             // linear bin position offset (0 to n-1 bins)\n  repeated SpeedHistogramByPeriod   speedsByPeriod = 7;        // repeated speed histogram\n  repeated SpeedSummaryByPeriod     speedSummaryByPeriod = 8;  // repeated speed summary\n}\n\n"
  },
  {
    "path": "proto/temporal_references.proto",
    "content": "syntax = \"proto3\";\n\noption java_outer_classname = \"SharedStreetsTemporalReferencesProto\";\n\nenum PeriodSize {\n    OneSecond = 0;\n    FiveSeconds = 1;\n    TenSeconds = 2;\n    FifteenSeconds = 3;\n    ThirtySeconds = 4;\n    OneMinute = 5;\n    FiveMinutes = 6;\n    TenMinutes = 7;\n    FifteenMinutes = 8;\n    ThirtyMinutes = 9;\n    OneHour = 10;\n    OneDay = 11;\n    OneWeek = 12;\n    OneMonth = 13;\n    OneYear = 14;\n}\n\n// temporal references for SharedStreets events (in UTC)\n\nmessage TemporalPeriod {\n\n  PeriodSize periodSize = 1;\n  uint64 periodOffset = 2; // period offset from unix epoch\n                           // For periodSize = oneYear:\n                           //   1970-01-01 = 0\n                           //   2015-01-01 = 45\n                           // For periodSize = OneMonth:\n                           //   1970-01-01 = 0\n                           //   2015-01-01 = 540\n                           // For periodSize = OneSecond: periodOffset = UNIX timestamp\n\n}\n\n// template for storing weekly cycles of events in local time -- used as a template for developing application specific data standards\n// assumes Monday-Sunday week in local time. See OpenTraffic weekly speed data for example implementation.\nmessage WeeklyCycle {\n\n  uint32 year = 1;     // date for Monday of week (Monday midnight is zero for week cycle per ISO-8601)\n  uint32 month = 2;\n  uint32 day = 3;\n\n  PeriodSize periodSize = 4;\n\n  // repeated [...] periodData = ...; // replace with application specific data payload\n\n\n}\n"
  }
]