-
Notifications
You must be signed in to change notification settings - Fork 211
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposed representations of version 3 extensions #115
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package vector_tile; | ||
|
||
option optimize_for = LITE_RUNTIME; | ||
|
||
message Tile { | ||
|
||
// GeomType is described in section 4.3.4 of the specification | ||
enum GeomType { | ||
UNKNOWN = 0; | ||
POINT = 1; | ||
LINESTRING = 2; | ||
POLYGON = 3; | ||
CURVE = 4; // like a LineString, but a spline | ||
AREA = 5; // like a Polygon, but a spline | ||
} | ||
|
||
// Variant type encoding | ||
// The use of values is described in section 4.1 of the specification | ||
message Value { | ||
// No more than one of these values may be present in a valid message. | ||
// If no value is written, the message is null. | ||
|
||
optional string string_value = 1; | ||
optional float float_value = 2; | ||
optional double double_value = 3; | ||
optional int64 int_value = 4; | ||
optional uint64 uint_value = 5; | ||
optional sint64 sint_value = 6; | ||
optional bool bool_value = 7; | ||
|
||
// Even numbered elements refer to the nth key in the layer's keys list | ||
// Odd numbered elements refer to the nth value in the layer's values list | ||
repeated uint32 hash_value = 8 [ packed = true ]; | ||
|
||
// Each element refers to the nth value in the layer's values list | ||
repeated uint32 list_value = 9 [ packed = true ]; | ||
|
||
extensions 10 to max; | ||
} | ||
|
||
// Features are described in section 4.2 of the specification | ||
message Feature { | ||
// Use object_id if the id is not an integer | ||
optional uint64 id = 1; | ||
|
||
// Tags of this feature are encoded as repeated pairs of | ||
// integers. | ||
// A detailed description of tags is located in sections | ||
// 4.2 and 4.4 of the specification | ||
repeated uint32 tags = 2 [ packed = true ]; | ||
|
||
// The type of geometry stored in this feature. | ||
optional GeomType type = 3 [ default = UNKNOWN ]; | ||
|
||
// Contains a stream of commands and parameters (vertices). | ||
// A detailed description of geometry encoding is located in | ||
// section 4.3 of the specification. | ||
repeated uint32 geometry = 4 [ packed = true ]; | ||
|
||
// Representation of spline knots to be clarified: | ||
// https://github.com/mapbox/vector-tile-spec/issues/114 | ||
repeated double knots = 5 [ packed = true ]; | ||
|
||
// If present, marks the geometry as explicitly MultiPoint, | ||
// MultiLineString, or MultiPolygon | ||
optional bool multigeometry = 6; | ||
|
||
// If present, these are references into the layer's values, | ||
// one per node (excluding ClosePath) of the geometry, | ||
// either to a hash_value giving the keys and values of | ||
// the node's attributes, or to a null value, indicating | ||
// that the node has no attributes. | ||
repeated uint32 node_attributes = 7 [ packed = true ]; | ||
|
||
// If present, these are delta-encoded elevations for each | ||
// node (excluding ClosePath) in the geometry. If any nodes have only | ||
// two dimensions specified, the missing elevations must | ||
// be encoded here as NaN. Only finite elevations participate | ||
// in delta encoding: the delta of the elevation after | ||
// a NaN is relative to the last finite elevation. | ||
// Elevations are in meters above or below the WGS84 ellipsoid. | ||
repeated double node_elevations = 8 [ packed = true ]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A double here would take up quite a bit of space as it could not be delta encoded and would not use integers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the elevations are integers, the normalized doubles for those integers should still work as deltas and compress well, although not as well as plain integers. What would you prefer to do instead? Integer references into the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do agree there that is an exact-representation problem with doubles, and that the sum of the deltas might drift too much from the true elevation by the time you got to the end of a complex feature. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could do a custom byte stream that has separate type markers for integer deltas, floating deltas, and resets to absolute values periodically to address drift, but that is getting very complicated unless there is an existing spec for this kind of thing that we could point to. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that we should likely have an configuration to change the precision much like extent, delta encode the values as integers and apply an offset to the values. This means that you could likely highly compress almost set of z values. I think standardizing on distance from the ellipsoid is probably ideal distance from our offset, but could be very challenging if we are mixing 2d and 3d data as the 2d data is likely on the surface. Additionally, do you feel that layers should support both 2d and 3d features? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What unspecified elevation meansI guess my feeling was that 2D and 3D features could coexist, but that 2D features all implicitly had an elevation of 0. But that contracts GeoJSON, which says that coordinates are WGS84 but also that "In the absence of elevation values, applications sensitive to height or depth SHOULD interpret positions as being at local ground or sea level." Even if 2D and 3D can't be in the same layer, it has to be possible to render them together, so they have to be reconciled somehow. A tile-level declaration of local ground level relative to the ellipsoid could work, but just moves the responsibility of knowing the local ground level everywhere in the world to the tile creator. Maybe we could hedge and say that null/unspecified elevations are extruded to the highest intersecting point in any other features they are being rendered together with, so if there is a terrain layer, they inherit from it, but if there isn't, they are on the ellipsoid? Data typeThe precision scale on integer elevations sounds like it would work (aside from worries above about intermixing known and unknown elevations) and would keep the math exact. I do think it should be possible to have both specified and unspecified elevations within the same feature, because if you don't, you end up with data sets assigning magic values like "-999" to unknown elevations. So I think we should provide our own official magic value for explicit nulls within otherwise-3D features. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would unreasonable to expect that encoders and decoders know the actual elevation of the ground they are currently on in order to calculate the position of a point in 3d space. This would violate the concept of VTs being a single source of data if they had to reference another set of data to function. Additionally, I am still not completely convinced that elevation data should be different from the 2D data and could be all encoded in the same geometry. Your design here does enable easier backwards compatibility but also worries me about writing an efficient encoder/decoder and also would result in a slightly less compressed binary I would think. Putting data into the 2D case could also be a problem for purely vertical lines in 3d for example. In this 2d case the X,Y would be a line-string that never changed and therefore would be violating the guarantees of linestrings as this would resolve to simply a point. Granted this is not a big concern but should be noted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What unspecified elevation meansI agree that it's unreasonable to expect that encoders or decoders will know the ground elevation. But as far as I can tell, if no one knows what it is, the alternatives are:
Of these choices, I think the first is better, as unfortunate as it is, because I think the second is completely unworkable. One object or twoThe main argument I can make in favor of a separate object for the third dimension is that we are contemplating at least one more pseudo-dimension (arbitrary attributes), and there has been a request for another (the M-dimension from shapefile). If all of these dimensions live in the same object, then we either need 6 different versions of each operator or a bitfield that specifies all 6 ways to read each coordinate "pair".
My opinion is that giving each dimension its own object is both more compatible with the past (existing encoders and decoders do not need to change) and more future-proof because we can add whatever other parallel arrays may be necessary in the future as we think of other things that need to be encoded. Putting everything in the same object is neither compatible nor straightforwardly extensible. You are right that we currently forbid 0-length movetos and linetos. Does anything actually enforce this or require it, or is it in the spec only as encouragement for people not to bloat their tiles with do-nothing geometry operations? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It is more a reason to not bloat, but it is enforced in the tile creation operations currently.
I think we probably should keep attributes out of the geometry encoding section, but the 3d data encoding there might make sense. Just as a different way I solved this in another example, I put a |
||
|
||
// If present, this value represents the height of an | ||
// extrusion of the entire feature. | ||
optional double extruded_height = 9; | ||
|
||
// If present, gives the id of the feature as a reference | ||
// into the layer's values. If the id is an integer, use | ||
// the id field (1) instead. | ||
optional uint32 object_id = 10; | ||
} | ||
|
||
// Layers are described in section 4.1 of the specification | ||
message Layer { | ||
// Any compliant implementation must first read the version | ||
// number encoded in this message and choose the correct | ||
// implementation for this version number before proceeding to | ||
// decode other parts of this message. | ||
required uint32 version = 15 [ default = 1 ]; | ||
|
||
required string name = 1; | ||
|
||
// The actual features in this tile. | ||
repeated Feature features = 2; | ||
|
||
// Dictionary encoding for keys | ||
repeated string keys = 3; | ||
|
||
// Dictionary encoding for values | ||
repeated Value values = 4; | ||
|
||
// Although this is an "optional" field it is required by the specification. | ||
// See https://github.com/mapbox/vector-tile-spec/issues/47 | ||
optional uint32 extent = 5 [ default = 4096 ]; | ||
|
||
extensions 16 to max; | ||
} | ||
|
||
repeated Layer layers = 3; | ||
|
||
extensions 16 to 8191; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this would require that the spline reconnects with itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the
AREA
case? That's what I was thinking I meant, but I don't know enough about splines. Would it not work? In PostScript you can have spline-outlined areas like this.