1/** Copyright (c) 2010 Scott A. Crosby. <scott@sacrosby.com>
2
3   This program is free software: you can redistribute it and/or modify
4   it under the terms of the GNU Lesser General Public License as
5   published by the Free Software Foundation, either version 3 of the
6   License, or (at your option) any later version.
7
8   This program is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11   GNU Lesser General Public License for more details.
12
13   You should have received a copy of the GNU Lesser General Public License
14   along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16*/
17
18syntax = "proto2";
19
20option optimize_for = LITE_RUNTIME;
21option java_package = "crosby.binary";
22package OSMPBF;
23
24/* OSM Binary file format
25
26This is the master schema file of the OSM binary file format. This
27file is designed to support limited random-access and future
28extendability.
29
30A binary OSM file consists of a sequence of FileBlocks (please see
31fileformat.proto). The first fileblock contains a serialized instance
32of HeaderBlock, followed by a sequence of PrimitiveBlock blocks that
33contain the primitives.
34
35Each primitiveblock is designed to be independently parsable. It
36contains a string table storing all strings in that block (keys and
37values in tags, roles in relations, usernames, etc.) as well as
38metadata containing the precision of coordinates or timestamps in that
39block.
40
41A primitiveblock contains a sequence of primitive groups, each
42containing primitives of the same type (nodes, densenodes, ways,
43relations). Coordinates are stored in signed 64-bit integers. Lat&lon
44are measured in units <granularity> nanodegrees. The default of
45granularity of 100 nanodegrees corresponds to about 1cm on the ground,
46and a full lat or lon fits into 32 bits.
47
48Converting an integer to a lattitude or longitude uses the formula:
49$OUT = IN * granularity / 10**9$. Many encoding schemes use delta
50coding when representing nodes and relations.
51
52*/
53
54//////////////////////////////////////////////////////////////////////////
55//////////////////////////////////////////////////////////////////////////
56
57/* Contains the file header. */
58
59message HeaderBlock {
60  optional HeaderBBox bbox = 1;
61  /* Additional tags to aid in parsing this dataset */
62  repeated string required_features = 4;
63  repeated string optional_features = 5;
64
65  optional string writingprogram = 16;
66  optional string source = 17; // From the bbox field.
67}
68
69
70/** The bounding box field in the OSM header. BBOX, as used in the OSM
71header. Units are always in nanodegrees -- they do not obey
72granularity rules. */
73
74message HeaderBBox {
75   required sint64 left = 1;
76   required sint64 right = 2;
77   required sint64 top = 3;
78   required sint64 bottom = 4;
79}
80
81
82///////////////////////////////////////////////////////////////////////
83///////////////////////////////////////////////////////////////////////
84
85
86message PrimitiveBlock {
87  required StringTable stringtable = 1;
88  repeated PrimitiveGroup primitivegroup = 2;
89
90  // Granularity, units of nanodegrees, used to store coordinates in this block
91  optional int32 granularity = 17 [default=100];
92  // Offset value between the output coordinates coordinates and the granularity grid in unites of nanodegrees.
93  optional int64 lat_offset = 19 [default=0];
94  optional int64 lon_offset = 20 [default=0];
95
96// Granularity of dates, normally represented in units of milliseconds since the 1970 epoch.
97  optional int32 date_granularity = 18 [default=1000];
98
99
100  // Proposed extension:
101  //optional BBox bbox = XX;
102}
103
104// Group of OSMPrimitives. All primitives in a group must be the same type.
105message PrimitiveGroup {
106  repeated Node     nodes = 1;
107  optional DenseNodes dense = 2;
108  repeated Way      ways = 3;
109  repeated Relation relations = 4;
110  repeated ChangeSet changesets = 5;
111}
112
113
114/** String table, contains the common strings in each block.
115
116 Note that we reserve index '0' as a delimiter, so the entry at that
117 index in the table is ALWAYS blank and unused.
118
119 */
120message StringTable {
121   repeated bytes s = 1;
122}
123
124/* Optional metadata that may be included into each primitive. */
125message Info {
126   optional int32 version = 1 [default = -1];
127   optional int64 timestamp = 2;
128   optional int64 changeset = 3;
129   optional int32 uid = 4;
130   optional uint32 user_sid = 5; // String IDs
131}
132
133/** Optional metadata that may be included into each primitive. Special dense format used in DenseNodes. */
134message DenseInfo {
135   repeated int32 version = 1 [packed = true];
136   repeated sint64 timestamp = 2 [packed = true]; // DELTA coded
137   repeated sint64 changeset = 3 [packed = true]; // DELTA coded
138   repeated sint32 uid = 4 [packed = true]; // DELTA coded
139   repeated sint32 user_sid = 5 [packed = true]; // String IDs for usernames. DELTA coded
140}
141
142
143// THIS IS STUB DESIGN FOR CHANGESETS. NOT USED RIGHT NOW.
144// TODO:    REMOVE THIS?
145message ChangeSet {
146   required int64 id = 1;
147//
148//   // Parallel arrays.
149//   repeated uint32 keys = 2 [packed = true]; // String IDs.
150//   repeated uint32 vals = 3 [packed = true]; // String IDs.
151//
152//   optional Info info = 4;
153
154//   optional int64 created_at = 8;
155//   optional int64 closetime_delta = 9;
156//   optional bool open = 10;
157//   optional HeaderBBox bbox = 11;
158}
159
160
161message Node {
162   required sint64 id = 1;
163   // Parallel arrays.
164   repeated uint32 keys = 2 [packed = true]; // String IDs.
165   repeated uint32 vals = 3 [packed = true]; // String IDs.
166
167   optional Info info = 4; // May be omitted in omitmeta
168
169   required sint64 lat = 8;
170   required sint64 lon = 9;
171}
172
173/* Used to densly represent a sequence of nodes that do not have any tags.
174
175We represent these nodes columnwise as five columns: ID's, lats, and
176lons, all delta coded. When metadata is not omitted,
177
178We encode keys & vals for all nodes as a single array of integers
179containing key-stringid and val-stringid, using a stringid of 0 as a
180delimiter between nodes.
181
182   ( (<keyid> <valid>)* '0' )*
183 */
184
185message DenseNodes {
186   repeated sint64 id = 1 [packed = true]; // DELTA coded
187
188   //repeated Info info = 4;
189   optional DenseInfo denseinfo = 5;
190
191   repeated sint64 lat = 8 [packed = true]; // DELTA coded
192   repeated sint64 lon = 9 [packed = true]; // DELTA coded
193
194   // Special packing of keys and vals into one array. May be empty if all nodes in this block are tagless.
195   repeated int32 keys_vals = 10 [packed = true];
196}
197
198
199message Way {
200   required int64 id = 1;
201   // Parallel arrays.
202   repeated uint32 keys = 2 [packed = true];
203   repeated uint32 vals = 3 [packed = true];
204
205   optional Info info = 4;
206
207   repeated sint64 refs = 8 [packed = true];  // DELTA coded
208}
209
210message Relation {
211  enum MemberType {
212    NODE = 0;
213    WAY = 1;
214    RELATION = 2;
215  }
216   required int64 id = 1;
217
218   // Parallel arrays.
219   repeated uint32 keys = 2 [packed = true];
220   repeated uint32 vals = 3 [packed = true];
221
222   optional Info info = 4;
223
224   // Parallel arrays
225   repeated int32 roles_sid = 8 [packed = true];
226   repeated sint64 memids = 9 [packed = true]; // DELTA encoded
227   repeated MemberType types = 10 [packed = true];
228}
229
230