Full Code of jingsam/vector-tile-spec for AI

master f92513f13566 cached
12 files
83.8 KB
24.7k tokens
1 requests
Download .txt
Repository: jingsam/vector-tile-spec
Branch: master
Commit: f92513f13566
Files: 12
Total size: 83.8 KB

Directory structure:
gitextract_f4e7qftu/

├── 1.0.0/
│   ├── README.md
│   └── vector_tile.proto
├── 1.0.1/
│   ├── README.md
│   └── vector_tile.proto
├── 2.0/
│   ├── README.md
│   └── vector_tile.proto
├── 2.1/
│   ├── README.md
│   ├── README_zh.md
│   └── vector_tile.proto
├── CHANGELOG.md
├── CONTRIBUTING.md
└── README.md

================================================
FILE CONTENTS
================================================

================================================
FILE: 1.0.0/README.md
================================================
# vector-tile-spec

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in
this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).

## 1. Purpose

This specification attempts to create a standard for encoding of tiled geospatial data that can be shared across clients.

## 2. File format

The vector tile encoding scheme encodes vector data for a tile in a space efficient manner. It is designed to be used in browsers or serverside applications for fast rendering or lookups of feature data.

Vector Tiles use [Google Protocol buffers](https://developers.google.com/protocol-buffers/) as a container format. It is exclusively geared towards square pixel tiles in [Spherical Mercator projection](http://wiki.openstreetmap.org/wiki/Mercator).

## 3. Internal structure

A vector tile can consist of one or more named layers and containing one or more features.

Features contain an id, attributes, and geometries: either point, linestring, or polygon.

Geometries are stored as an a single array of integers that represent an command,x,y stream (where command is a rendering command like move_to or line_to). Commands are encoded only when they change. Geometries are clipped, reprojected into spherical mercator, converted to screen coordinates, and [delta](http://en.wikipedia.org/wiki/Delta_encoding) and [zigzag](https://developers.google.com/protocol-buffers/docs/encoding#types) encoded.

Feature attributes are encoded as key:value pairs which are dictionary encoded at the layer level for compact storage of any repeated keys or values. Values use [variant](https://developers.google.com/protocol-buffers/docs/encoding#varints) type encoding supporting both unicode strings, boolean values, and various integer and floating point types.

For example, a GeoJSON feature like:

```json
{
    "type": "FeatureCollection", 
    "features": [
        {
            "geometry": {
                "type": "Point", 
                "coordinates": [
                    -8247861.1000836585, 
                    4970241.327215323
                ]
            }, 
            "type": "Feature", 
            "properties": {
                "hello": "world"
            }
        }
    ]
}
```

Would be structured like:

```js
layers {
  name: "points"
  features {
    id: 1
    tags: 0
    tags: 0
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  keys: "hello"
  values {
    string_value: "world"
  }
  extent: 4096
  version: 2
}
```

The complete and authoritative details on encoding are part of the code comments for the [vector tile protobuf schema document](vector_tile.proto).


================================================
FILE: 1.0.0/vector_tile.proto
================================================
// Protocol Version 1

package mapnik.vector;

option optimize_for = LITE_RUNTIME;

message tile {
        enum GeomType {
             Unknown = 0;
             Point = 1;
             LineString = 2;
             Polygon = 3;
        }

        // Variant type encoding
        message value {
                // Exactly one of these values may be present in a valid message
                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;

                extensions 8 to max;
        }

        message feature {
                optional uint64 id = 1;

                // Tags of this feature. Even numbered values refer to the nth
                // value in the keys list on the tile message, odd numbered
                // values refer to the nth value in the values list on the tile
                // message.
                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). The
                // repeat count is shifted to the left by 3 bits. This means
                // that the command has 3 bits (0-7). The repeat count
                // indicates how often this command is to be repeated. Defined
                // commands are:
                // - MoveTo:    1   (2 parameters follow)
                // - LineTo:    2   (2 parameters follow)
                // - ClosePath: 7   (no parameters follow)
                //
                // Commands are encoded as uint32 varints. Vertex parameters
                // are encoded as deltas to the previous position and, as they
                // may be negative, are further "zigzag" encoded as unsigned
                // 32-bit ints:
                //
                //   n = (n << 1) ^ (n >> 31)
                //
                // Ex.: MoveTo(3, 6), LineTo(8, 12), LineTo(20, 34), ClosePath
                // Encoded as: [ 9 6 12 18 10 12 24 44 15 ]
                //               |       |              `> [00001 111] command type 7 (ClosePath), length 1
                //               |       |       ===== relative LineTo(+12, +22) == LineTo(20, 34)
                //               |       | ===== relative LineTo(+5, +6) == LineTo(8, 12)
                //               |       `> [00010 010] = command type 2 (LineTo), length 2
                //               | ==== relative MoveTo(+3, +6)
                //               `> [00001 001] = command type 1 (MoveTo), length 1
                //
                // The original position is (0,0).
                repeated uint32 geometry = 4 [ packed = true ];
        }

        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;

                // The bounding box in this tile spans from 0..4095 units
                optional uint32 extent = 5 [ default = 4096 ];

                extensions 16 to max;
        }

        repeated layer layers = 3;

        extensions 16 to 8191;
}


================================================
FILE: 1.0.1/README.md
================================================
# vector-tile-spec

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in
this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).

## 1. Purpose

This specification attempts to create a standard for encoding of tiled geospatial data that can be shared across clients.

## 2. File format

The vector tile encoding scheme encodes vector data for a tile in a space efficient manner. It is designed to be used in browsers or serverside applications for fast rendering or lookups of feature data.

Vector Tiles use [Google Protocol buffers](https://developers.google.com/protocol-buffers/) as a container format. It is exclusively geared towards square pixel tiles in [Spherical Mercator projection](http://wiki.openstreetmap.org/wiki/Mercator).

## 3. Internal structure

A vector tile can consist of one or more named layers and containing one or more features.

Features contain an id, attributes, and geometries: either point, linestring, or polygon.

Geometries are stored as a single array of integers that represent a command,x,y stream (where command is a rendering command like move_to or line_to). Commands are encoded only when they change. Geometries are clipped, reprojected into spherical mercator, converted to screen coordinates, and [delta](http://en.wikipedia.org/wiki/Delta_encoding) and [zigzag](https://developers.google.com/protocol-buffers/docs/encoding#types) encoded.

Feature attributes are encoded as key:value pairs which are dictionary encoded at the layer level for compact storage of any repeated keys or values. Values use [varint](https://developers.google.com/protocol-buffers/docs/encoding#varints) type encoding supporting both unicode strings, boolean values, and various integer and floating point types.

For example, a GeoJSON feature like:

```json
{
    "type": "FeatureCollection", 
    "features": [
        {
            "geometry": {
                "type": "Point", 
                "coordinates": [
                    -8247861.1000836585, 
                    4970241.327215323
                ]
            }, 
            "type": "Feature", 
            "properties": {
                "hello": "world"
            }
        }
    ]
}
```

Would be structured like:

```js
layers {
  name: "points"
  features {
    id: 1
    tags: 0
    tags: 0
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  keys: "hello"
  values {
    string_value: "world"
  }
  extent: 4096
  version: 2
}
```

The complete and authoritative details on encoding are part of the code comments for the [vector tile protobuf schema document](vector_tile.proto).


================================================
FILE: 1.0.1/vector_tile.proto
================================================
// Protocol Version 1

package vector_tile;

option optimize_for = LITE_RUNTIME;

message Tile {
        enum GeomType {
             UNKNOWN = 0;
             POINT = 1;
             LINESTRING = 2;
             POLYGON = 3;
        }

        // Variant type encoding
        message Value {
                // Exactly one of these values may be present in a valid message
                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;

                extensions 8 to max;
        }

        message Feature {
                optional uint64 id = 1 [ default = 0 ];

                // Tags of this feature are encoded as repeated pairs of
                // integers. Even indexed values (n, beginning with 0) are
                // themselves indexes into the layer's keys list. Odd indexed
                // values (n+1) are indexes into the layer's values list.
                // The first (n=0) tag of a feature, therefore, has a key of
                // layer.keys[feature.tags[0]] and a value of 
                // layer.values[feature.tags[1]].
                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). The
                // repeat count is shifted to the left by 3 bits. This means
                // that the command has 3 bits (0-7). The repeat count
                // indicates how often this command is to be repeated. Defined
                // commands are:
                // - MoveTo:    1   (2 parameters follow)
                // - LineTo:    2   (2 parameters follow)
                // - ClosePath: 7   (no parameters follow)
                //
                // Commands are encoded as uint32 varints. Vertex parameters
                // are encoded as deltas to the previous position and, as they
                // may be negative, are further "zigzag" encoded as unsigned
                // 32-bit ints:
                //
                //   n = (n << 1) ^ (n >> 31)
                //
                // Ex.: MoveTo(3, 6), LineTo(8, 12), LineTo(20, 34), ClosePath
                // Encoded as: [ 9 6 12 18 10 12 24 44 15 ]
                //               |       |              `> [00001 111] command type 7 (ClosePath), length 1
                //               |       |       ===== relative LineTo(+12, +22) == LineTo(20, 34)
                //               |       | ===== relative LineTo(+5, +6) == LineTo(8, 12)
                //               |       `> [00010 010] = command type 2 (LineTo), length 2
                //               | ==== relative MoveTo(+3, +6)
                //               `> [00001 001] = command type 1 (MoveTo), length 1
                //
                // The original position is (0,0).
                repeated uint32 geometry = 4 [ packed = true ];
        }

        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;

                // The bounding box in this tile spans from 0..4095 units
                optional uint32 extent = 5 [ default = 4096 ];

                extensions 16 to max;
        }

        repeated Layer layers = 3;

        extensions 16 to 8191;
}


================================================
FILE: 2.0/README.md
================================================
# Vector Tile Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in
this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).

## 1. Purpose

This document specifies a space-efficient encoding format for tiled geographic vector data. It is designed to be used in browsers or server-side applications for fast rendering or lookups of feature data.

## 2. File Format

The Vector Tile format uses [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) as a encoding format. Protocol Buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data.

## 2.1. File Extension

The filename extension for Vector Tile files SHOULD be `mvt`. For example, a file might be named `vector.mvt`.

## 2.2. Multipurpose Internet Mail Extensions (MIME)

When serving Vector Tiles the MIME type SHOULD be `application/vnd.mapbox-vector-tile`.

## 3. Projection and Bounds

A Vector Tile represents data based on a square extent within a projection. A Vector Tile SHOULD NOT contain information about its bounds and projection. The file format assumes that the decoder knows the bounds and projection of a Vector Tile before decoding it.

[Web Mercator](https://en.wikipedia.org/wiki/Web_Mercator) is the projection of reference, and [the Google tile scheme](http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/) is the tile extent convention of reference. Together, they provide a 1-to-1 relationship between a specific geographical area, at a specific level of detail, and a path such as `https://example.com/17/65535/43602.mvt`.

Vector Tiles MAY be used to represent data with any projection and tile extent scheme.

## 4. Internal Structure

This specification describes the structure of data within a Vector Tile. The reader should have an understanding of the [Vector Tile protobuf schema document](vector_tile.proto) and the structures it defines.

### 4.1. Layers

A Vector Tile consists of a set of named layers. A layer contains geometric features and their metadata. The layer format is designed so that the data required for a layer is contiguous in memory, and so that layers can be appended to a Vector Tile without modifying existing data.

A Vector Tile SHOULD contain at least one layer. A layer SHOULD contain at least one feature.

A layer MUST contain a `version` field with the major version number of the Vector Tile specification to which the layer adheres. For example, a layer adhering to version 2.1 of the specification contains a `version` field with the integer value `2`. The `version` field SHOULD be the first field within the layer. Decoders SHOULD parse the `version` first to ensure that they are capable of decoding each layer. When a Vector Tile consumer encounters a Vector Tile layer with an unknown version, it MAY make a best-effort attempt to interpret the layer, or it MAY skip the layer. In either case it SHOULD continue to process subsequent layers in the Vector Tile.

A layer MUST contain a `name` field. A Vector Tile MUST NOT contain two or more layers whose `name` values are byte-for-byte identical. Prior to appending a layer to an existing Vector Tile, an encoder MUST check the existing `name` fields in order to prevent duplication.

Each feature in a layer (see below) may have one or more key-value pairs as its metadata. The keys and values are indices into two lists, `keys` and `values`, that are shared across the layer's features.

Each element in the `keys` field of the layer is a string. The `keys` include all the keys of features used in the layer, and each key may be referenced by its positional index in this set of `keys`, with the first key having an index of 0. The set of `keys` SHOULD NOT contain two or more values which are byte-for-byte identical.

Each element in the `values` field of the layer encodes a value of any of several types (see below). The `values` represent all the values of features used in the layer, and each value may be referenced by its positional index in this set of `values`, with the first value having an index of 0. The set of `values` SHOULD NOT contain two or more values of the same type which are byte-for-byte identical.

In order to support values of varying string, boolean, integer, and floating point types, the protobuf encoding of the `value` field consists of a set of `optional` fields. A value MUST contain exactly one of these optional fields.

A layer MUST contain an `extent` that describes the width and height of the tile in integer coordinates. The geometries within the Vector Tile MAY extend past the bounds of the tile's area as defined by the `extent`. Geometries that extend past the tile's area as defined by `extent` are often used as a buffer for rendering features that overlap multiple adjacent tiles.

For example, if a tile has an `extent` of 4096, values between 0 and 4095 are considered within the tile's extent. A point at `(0,10)` or `(4095,10)` is within the extent of the tile. A point at `(-1,10)` or `(4096,10)` is outside the extent of the tile.

### 4.2. Features

A feature MUST contain a `geometry` field.

A feature MUST contain a `type` field as described in the Geometry Types section.

A feature MAY contain a `tags` field. Feature-level metadata, if any, SHOULD be stored in the `tags` field.

A feature MAY contain an `id` field. If a feature has an `id` field, the value of the `id` SHOULD be unique among the features of the parent layer.

### 4.3. Geometry Encoding

Geometry data in a Vector Tile is defined in a screen coordinate system. The upper left corner of the tile (as displayed by default) is the origin of the coordinate system. The X axis is positive to the right, and the Y axis is positive downward. Coordinates within a geometry MUST be integers.

A geometry is encoded as a sequence of 32 bit unsigned integers in the `geometry` field of a feature. Each integer is either a `CommandInteger` or a `ParameterInteger`. A decoder interprets these as an ordered series of operations to generate the geometry.

Commands refer to positions relative to a "cursor", which is a redefinable point. For the first command in a feature, the cursor is at `(0,0)` in the coordinate system. Some commands move the cursor, affecting subsequent commands.

#### 4.3.1. Command Integers

A `CommandInteger` indicates a command to be executed, as a command ID, and the number of times that the command will be executed, as a command count.

A command ID is encoded as an unsigned integer in the least significant 3 bits of the `CommandInteger`, and is in the range 0 through 7, inclusive. A command count is encoded as an unsigned integer in the remaining 29 bits of a `CommandInteger`, and is in the range `0` through `pow(2, 29) - 1`, inclusive.

A command ID, a command count, and a `CommandInteger` are related by these bitwise operations:

```javascript
CommandInteger = (id & 0x7) | (count << 3)
```

```javascript
id = CommandInteger & 0x7
```

```javascript
count = CommandInteger >> 3
```

A command ID specifies one of the following commands:

|  Command     |  Id  | Parameters    | Parameter Count |
| ------------ |:----:| ------------- | --------------- |
| MoveTo       | `1`  | `dX`, `dY`    | 2               |
| LineTo       | `2`  | `dX`, `dY`    | 2               |
| ClosePath    | `7`  | No parameters | 0               |

##### Example Command Integers

| Command   |  ID  | Count | CommandInteger | Binary Representation `[Count][Id]`      |
| --------- |:----:|:-----:|:--------------:|:----------------------------------------:|
| MoveTo    | `1`  | `1`   | `9`            | `[00000000 00000000 0000000 00001][001]` |
| MoveTo    | `1`  | `120` | `961`          | `[00000000 00000000 0000011 11000][001]` |
| LineTo    | `2`  | `1`   | `10`           | `[00000000 00000000 0000000 00001][010]` |
| LineTo    | `2`  | `3`   | `26`           | `[00000000 00000000 0000000 00011][010]` |
| ClosePath | `7`  | `1`   | `15`           | `[00000000 00000000 0000000 00001][111]` |


#### 4.3.2. Parameter Integers

Commands requiring parameters are followed by a `ParameterInteger` for each parameter required by that command. The number of `ParameterIntegers` that follow a `CommandInteger` is equal to the parameter count of a command multiplied by the command count of the `CommandInteger`. For example, a `CommandInteger` with a `MoveTo` command with a command count of 3 will be followed by 6 `ParameterIntegers`.

A `ParameterInteger` is [zigzag](https://developers.google.com/protocol-buffers/docs/encoding#types) encoded so that small negative and positive values are both encoded as small integers. To encode a parameter value to a `ParameterInteger` the following formula is used:

```javascript
ParameterInteger = (value << 1) ^ (value >> 31)
```

Parameter values greater than `pow(2,31) - 1` or less than `-1 * (pow(2,31) - 1)` are not supported.

The following formula is used to decode a `ParameterInteger` to a value:

```javascript
value = ((ParameterInteger >> 1) ^ (-(ParameterInteger & 1)))
```

#### 4.3.3. Command Types

For all descriptions of commands the initial position of the cursor shall be described to be at the coordinates `(cX, cY)` where `cX` is the position of the cursor on the X axis and `cY` is the position of the `cursor` on the Y axis.

##### 4.3.3.1. MoveTo Command

A `MoveTo` command with a command count of `n` MUST be immediately followed by `n` pairs of `ParameterInteger`s. Each pair `(dX, dY)`:

1. Defines the coordinate `(pX, pY)`, where `pX = cX + dX` and `pY = cY + dY`.
   * Within POINT geometries, this coordinate defines a new point.
   * Within LINESTRING geometries, this coordinate defines the starting vertex of a new line.
   * Within POLYGON geometries, this coordinate defines the starting vertex of a new linear ring.
2. Moves the cursor to `(pX, pY)`.

#### 4.3.3.2. LineTo Command

A `LineTo` command with a command count of `n` MUST be immediately followed by `n` pairs of `ParameterInteger`s. Each pair `(dX, dY)`:

1. Defines a segment beginning at the cursor `(cX, cY)` and ending at the coordinate `(pX, pY)`, where `pX = cX + dX` and `pY = cY + dY`.
   * Within LINESTRING geometries, this segment extends the current line.
   * Within POLYGON geometries, this segment extends the current linear ring.
2. Moves the cursor to `(pX, pY)`.

For any pair of `(dX, dY)` the `dX` and `dY` SHOULD NOT both be `0`.

#### 4.3.3.3. ClosePath Command

A `ClosePath` command MUST have a command count of 1 and no parameters. The command closes the current linear ring of a POLYGON geometry via a line segment beginning at the cursor `(cX, cY)` and ending at the starting vertex of the current linear ring.

This command does not change the cursor position.

#### 4.3.4. Geometry Types

The `geometry` field is described in each feature by the `type` field which must be a value in the enum `GeomType`. The following geometry types are supported:

* UNKNOWN
* POINT
* LINESTRING
* POLYGON

Geometry collections are not supported.

##### 4.3.4.1. Unknown Geometry Type

The specification purposefully leaves an unknown geometry type as an option. This geometry type encodes experimental geometry types that an encoder MAY choose to implement. Decoders MAY ignore any features of this geometry type.

##### 4.3.4.2. Point Geometry Type

The `POINT` geometry type encodes a point or multipoint geometry. The geometry command sequence for a point geometry MUST consist of a single `MoveTo` command with a command count greater than 0.

If the `MoveTo` command for a `POINT` geometry has a command count of 1, then the geometry MUST be interpreted as a single point; otherwise the geometry MUST be interpreted as a multipoint geometry, wherein each pair of `ParameterInteger`s encodes a single point.

##### 4.3.4.3. Linestring Geometry Type

The `LINESTRING` geometry type encodes a linestring or multilinestring geometry. The geometry command sequence for a linestring geometry MUST consist of one or more repetitions of the following sequence: 

1. A `MoveTo` command with a command count of 1
2. A `LineTo` command with a command count greater than 0

If the command sequence for a `LINESTRING` geometry type includes only a single `MoveTo` command then the geometry MUST be interpreted as a single linestring; otherwise the geometry MUST be interpreted as a multilinestring geometry, wherein each `MoveTo` signals the beginning of a new linestring.

##### 4.3.4.4. Polygon Geometry Type

The `POLYGON` geometry type encodes a polygon or multipolygon geometry, each polygon consisting of exactly one exterior ring that contains zero or more interior rings. The geometry command sequence for a polygon consists of one or more repetitions of the following sequence:

1. An `ExteriorRing`
2. Zero or more `InteriorRing`s

Each `ExteriorRing` and `InteriorRing` MUST consist of the following sequence:

1. A `MoveTo` command with a command count of 1
2. A `LineTo` command with a command count greater than 1
3. A `ClosePath` command

An exterior ring is DEFINED as a linear ring having a positive area as calculated by applying the [surveyor's formula](https://en.wikipedia.org/wiki/Shoelace_formula) to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the exterior ring's winding order appear clockwise.

An interior ring is DEFINED as a linear ring having a negative area as calculated by applying the [surveyor's formula](https://en.wikipedia.org/wiki/Shoelace_formula) to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the interior ring's winding order appear counterclockwise.

If the command sequence for a `POLYGON` geometry type includes only a single exterior ring then the geometry MUST be interpreted as a single polygon; otherwise the geometry MUST be interpreted as a multipolygon geometry, wherein each exterior ring signals the beginning of a new polygon. If a polygon has interior rings they MUST be encoded directly after the exterior ring of the polygon to which they belong.

Linear rings MUST be geometric objects that have no anomalous geometric points, such as self-intersection or self-tangency. The position of the cursor before calling the `ClosePath` command of a linear ring SHALL NOT repeat the same position as the first point in the linear ring as this would create a zero-length line segment. A linear ring SHOULD NOT have an area calculated by the surveyor's formula equal to zero, as this would signify a ring with anomalous geometric points.

Polygon geometries MUST NOT have any interior rings that intersect and interior rings MUST be enclosed by the exterior ring.

#### 4.3.5. Example Geometry Encodings

##### 4.3.5.1. Example Point

An example encoding of a point located at:

* (25,7)

This would require a single command:

* MoveTo(+25, +17)

```
Encoded as: [ 9 50 34 ]
              | |  `> Decoded: ((34 >> 1) ^ (-(34 & 1))) = +17
              | `> Decoded: ((50 >> 1) ^ (-(50 & 1))) = +25
              | ===== relative MoveTo(+25, +17) == create point (25,17)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.2. Example Multi Point

An example encoding of two points located at:

* (5,7)
* (3,2)

This would require two commands:

* MoveTo(+5,+7)
* MoveTo(-2,-5)

```
Encoded as: [ 17 10 14 3 9 ]
               |  |  | | `> Decoded: ((9 >> 1) ^ (-(9 & 1))) = -5
               |  |  | `> Decoded: ((3 >> 1) ^ (-(3 & 1))) = -2
               |  |  | === relative MoveTo(-2, -5) == create point (3,2)
               |  |  `> Decoded: ((34 >> 1) ^ (-(34 & 1))) = +7
               |  `> Decoded: ((50 >> 1) ^ (-(50 & 1))) = +5
               | ===== relative MoveTo(+25, +17) == create point (25,17)
               `> [00010 001] = command id 1 (MoveTo), length 2
```

##### 4.3.5.3. Example Linestring

An example encoding of a line with the points:

* (2,2)
* (2,10)
* (10,10)

This would require three commands:

* MoveTo(+2,+2)
* LineTo(+0,+8)
* LineTo(+8,+0)

```
Encoded as: [ 9 4 4 18 0 16 16 0 ]
              |      |      ==== relative LineTo(+8, +0) == Line to Point (10, 10)
              |      | ==== relative LineTo(+0, +8) == Line to Point (2, 10)
              |      `> [00010 010] = command id 2 (LineTo), length 2
              | === relative MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.4. Example Multi Linestring

An example encoding of two lines with the points:

* Line 1:
  * (2,2)
  * (2,10)
  * (10,10)
* Line 2:
  * (1,1)
  * (3,5)

This would require the following commands:

* MoveTo(+2,+2)
* LineTo(+0,+8)
* LineTo(+8,+0)
* MoveTo(-9,-9)
* LineTo(+2,+4)

```
Encoded as: [ 9 4 4 18 0 16 16 0 9 17 17 10 4 8 ]
              |      |           |        | === relative LineTo(+2, +4) == Line to Point (3,5)
              |      |           |        `> [00001 010] = command id 2 (LineTo), length 1
              |      |           | ===== relative MoveTo(-9, -9) == Start new line at (1,1)
              |      |           `> [00001 001] = command id 1 (MoveTo), length 1
              |      |      ==== relative LineTo(+8, +0) == Line to Point (10, 10)
              |      | ==== relative LineTo(+0, +8) == Line to Point (2, 10)
              |      `> [00010 010] = command id 2 (LineTo), length 2
              | === relative MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.5. Example Polygon

An example encoding of a polygon feature that has the points:

* (3,6)
* (8,12)
* (20,34)
* (3,6) *Path Closing as Last Point*

Would encoded by using the following commands:

* MoveTo(3, 6)
* LineTo(5, 6)
* LineTo(12, 22)
* ClosePath

```
Encoded as: [ 9 6 12 18 10 12 24 44 15 ]
              |       |              `> [00001 111] command id 7 (ClosePath), length 1
              |       |       ===== relative LineTo(+12, +22) == Line to Point (20, 34)
              |       | ===== relative LineTo(+5, +6) == Line to Point (8, 12)
              |       `> [00010 010] = command id 2 (LineTo), length 2
              | ==== relative MoveTo(+3, +6)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.6. Example Multi Polygon

An example of a more complex encoding of two polygons, one with a hole. The position of the points for the polygons are shown below. The winding order of the polygons is VERY important in this example as it signifies the difference between interior rings and a new polygon.

* Polygon 1:
  * Exterior Ring:
    * (0,0)
    * (10,0)
    * (10,10)
    * (0,10)
    * (0,0) *Path Closing as Last Point*
* Polygon 2:
  * Exterior Ring:
    * (11,11)
    * (20,11)
    * (20,20)
    * (11,20)
    * (11,11) *Path Closing as Last Point*
  * Interior Ring:
    * (13,13)
    * (13,17)
    * (17,17)
    * (17,13)
    * (13,13) *Path Closing as Last Point*

This polygon would be encoded with the following set of commands:

* MoveTo(+0,+0)
* LineTo(+10,+0)
* LineTo(+0,+10)
* LineTo(-10,+0) // Cursor at 0,10 after this command
* ClosePath // End of Polygon 1
* MoveTo(+11,+1) // NOTE THAT THIS IS RELATIVE TO LAST LINETO!
* LineTo(+9,+0)
* LineTo(+0,+9)
* LineTo(-9,+0) // Cursor at 11,20 after this command
* ClosePath // This is a new polygon because area is positive!
* MoveTo(+2,-7) // NOTE THAT THIS IS RELATIVE TO LAST LINETO!
* LineTo(+0,+4)
* LineTo(+4,+0)
* LineTo(+0,-4) // Cursor at 17,13
* ClosePath // This is an interior ring because area is negative!

### 4.4. Feature Attributes

Feature attributes are encoded as pairs of integers in the `tag` field of a feature. The first integer in each pair represents the zero-based index of the key in the `keys` set of the `layer` to which the feature belongs. The second integer in each pair represents the zero-based index of the value in the `values` set of the `layer` to which the feature belongs. Every key index MUST be unique within that feature such that no other attribute pair within that feature has the same key index. A feature MUST have an even number of `tag` fields. A feature `tag` field MUST NOT contain a key index or value index greater than or equal to the number of elements in the layer's `keys` or `values` set, respectively.

### 4.5. Example

For example, a GeoJSON feature like:

```json
{
    "type": "FeatureCollection",
    "features": [
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -8247861.1000836585,
                    4970241.327215323
                ]
            },
            "type": "Feature",
            "properties": {
                "hello": "world",
                "h": "world",
                "count": 1.23
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -8247861.1000836585,
                    4970241.327215323
                ]
            },
            "type": "Feature",
            "properties": {
                "hello": "again",
                "count": 2
            }
        }
    ]
}
```

Could be structured like:

```js
layers {
  version: 2
  name: "points"
  features: {
    id: 1
    tags: 0
    tags: 0
    tags: 1
    tags: 0
    tags: 2
    tags: 1
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  features {
    id: 1
    tags: 0
    tags: 2
    tags: 2
    tags: 3
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  keys: "hello"
  keys: "h"
  keys: "count"
  values: {
    string_value: "world"
  }
  values: {
    double_value: 1.23
  }
  values: {
    string_value: "again"
  }
  values: {
    int_value: 2
  }
  extent: 4096
}
```

Keep in mind the exact values for the geometry would differ based on the projection and extent of the tile.


================================================
FILE: 2.0/vector_tile.proto
================================================
// Protocol Version 1

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;
        }

        // Variant type encoding
        // The use of values is described in section 4.1 of the specification
        message Value {
                // Exactly one of these values must be present in a valid message
                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;

                extensions 8 to max;
        }

        // Features are described in section 4.2 of the specification
        message Feature {
                optional uint64 id = 1 [ default = 0 ];

                // 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 on geometry encoding is located in 
                // section 4.3 of the specification.
                repeated uint32 geometry = 4 [ packed = true ];
        }

        // 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;

                // The bounding box in this tile spans from 0..4095 units
                // 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;
}


================================================
FILE: 2.1/README.md
================================================
# Vector Tile Specification

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in
this document are to be interpreted as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt).

## 1. Purpose

This document specifies a space-efficient encoding format for tiled geographic vector data. It is designed to be used in browsers or server-side applications for fast rendering or lookups of feature data.

## 2. File Format

The Vector Tile format uses [Google Protocol Buffers](https://developers.google.com/protocol-buffers/) as a encoding format. Protocol Buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data.

## 2.1. File Extension

The filename extension for Vector Tile files SHOULD be `mvt`. For example, a file might be named `vector.mvt`.

## 2.2. Multipurpose Internet Mail Extensions (MIME)

When serving Vector Tiles the MIME type SHOULD be `application/vnd.mapbox-vector-tile`.

## 3. Projection and Bounds

A Vector Tile represents data based on a square extent within a projection. A Vector Tile SHOULD NOT contain information about its bounds and projection. The file format assumes that the decoder knows the bounds and projection of a Vector Tile before decoding it.

[Web Mercator](https://en.wikipedia.org/wiki/Web_Mercator) is the projection of reference, and [the Google tile scheme](http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/) is the tile extent convention of reference. Together, they provide a 1-to-1 relationship between a specific geographical area, at a specific level of detail, and a path such as `https://example.com/17/65535/43602.mvt`.

Vector Tiles MAY be used to represent data with any projection and tile extent scheme.

## 4. Internal Structure

This specification describes the structure of data within a Vector Tile. The reader should have an understanding of the [Vector Tile protobuf schema document](vector_tile.proto) and the structures it defines.

### 4.1. Layers

A Vector Tile consists of a set of named layers. A layer contains geometric features and their metadata. The layer format is designed so that the data required for a layer is contiguous in memory, and so that layers can be appended to a Vector Tile without modifying existing data.

A Vector Tile SHOULD contain at least one layer. A layer SHOULD contain at least one feature.

A layer MUST contain a `version` field with the major version number of the Vector Tile specification to which the layer adheres. For example, a layer adhering to version 2.1 of the specification contains a `version` field with the integer value `2`. The `version` field SHOULD be the first field within the layer. Decoders SHOULD parse the `version` first to ensure that they are capable of decoding each layer. When a Vector Tile consumer encounters a Vector Tile layer with an unknown version, it MAY make a best-effort attempt to interpret the layer, or it MAY skip the layer. In either case it SHOULD continue to process subsequent layers in the Vector Tile.

A layer MUST contain a `name` field. A Vector Tile MUST NOT contain two or more layers whose `name` values are byte-for-byte identical. Prior to appending a layer to an existing Vector Tile, an encoder MUST check the existing `name` fields in order to prevent duplication.

Each feature in a layer (see below) may have one or more key-value pairs as its metadata. The keys and values are indices into two lists, `keys` and `values`, that are shared across the layer's features.

Each element in the `keys` field of the layer is a string. The `keys` include all the keys of features used in the layer, and each key may be referenced by its positional index in this set of `keys`, with the first key having an index of 0. The set of `keys` SHOULD NOT contain two or more values which are byte-for-byte identical.

Each element in the `values` field of the layer encodes a value of any of several types (see below). The `values` represent all the values of features used in the layer, and each value may be referenced by its positional index in this set of `values`, with the first value having an index of 0. The set of `values` SHOULD NOT contain two or more values of the same type which are byte-for-byte identical.

In order to support values of varying string, boolean, integer, and floating point types, the protobuf encoding of the `value` field consists of a set of `optional` fields. A value MUST contain exactly one of these optional fields.

A layer MUST contain an `extent` that describes the width and height of the tile in integer coordinates. The geometries within the Vector Tile MAY extend past the bounds of the tile's area as defined by the `extent`. Geometries that extend past the tile's area as defined by `extent` are often used as a buffer for rendering features that overlap multiple adjacent tiles.

For example, if a tile has an `extent` of 4096, coordinate units within the tile refer to 1/4096th of its square dimensions. A coordinate of 0 is on the top or left edge of the tile, and a coordinate of 4096 is on the bottom or right edge. Coordinates from 1 through 4095 inclusive are fully within the extent of the tile, and coordinates less than 0 or greater than 4096 are fully outside the extent of the tile.  A point at `(1,10)` or `(4095,10)` is within the extent of the tile. A point at `(0,10)` or `(4096,10)` is on the edge of the extent. A point at `(-1,10)` or `(4097,10)` is outside the extent of the tile.

### 4.2. Features

A feature MUST contain a `geometry` field.

A feature MUST contain a `type` field as described in the Geometry Types section.

A feature MAY contain a `tags` field. Feature-level metadata, if any, SHOULD be stored in the `tags` field.

A feature MAY contain an `id` field. If a feature has an `id` field, the value of the `id` SHOULD be unique among the features of the parent layer.

### 4.3. Geometry Encoding

Geometry data in a Vector Tile is defined in a screen coordinate system. The upper left corner of the tile (as displayed by default) is the origin of the coordinate system. The X axis is positive to the right, and the Y axis is positive downward. Coordinates within a geometry MUST be integers.

A geometry is encoded as a sequence of 32 bit unsigned integers in the `geometry` field of a feature. Each integer is either a `CommandInteger` or a `ParameterInteger`. A decoder interprets these as an ordered series of operations to generate the geometry.

Commands refer to positions relative to a "cursor", which is a redefinable point. For the first command in a feature, the cursor is at `(0,0)` in the coordinate system. Some commands move the cursor, affecting subsequent commands.

#### 4.3.1. Command Integers

A `CommandInteger` indicates a command to be executed, as a command ID, and the number of times that the command will be executed, as a command count.

A command ID is encoded as an unsigned integer in the least significant 3 bits of the `CommandInteger`, and is in the range 0 through 7, inclusive. A command count is encoded as an unsigned integer in the remaining 29 bits of a `CommandInteger`, and is in the range `0` through `pow(2, 29) - 1`, inclusive.

A command ID, a command count, and a `CommandInteger` are related by these bitwise operations:

```javascript
CommandInteger = (id & 0x7) | (count << 3)
```

```javascript
id = CommandInteger & 0x7
```

```javascript
count = CommandInteger >> 3
```

A command ID specifies one of the following commands:

|  Command     |  Id  | Parameters    | Parameter Count |
| ------------ |:----:| ------------- | --------------- |
| MoveTo       | `1`  | `dX`, `dY`    | 2               |
| LineTo       | `2`  | `dX`, `dY`    | 2               |
| ClosePath    | `7`  | No parameters | 0               |

##### Example Command Integers

| Command   |  ID  | Count | CommandInteger | Binary Representation `[Count][Id]`      |
| --------- |:----:|:-----:|:--------------:|:----------------------------------------:|
| MoveTo    | `1`  | `1`   | `9`            | `[00000000 00000000 0000000 00001][001]` |
| MoveTo    | `1`  | `120` | `961`          | `[00000000 00000000 0000011 11000][001]` |
| LineTo    | `2`  | `1`   | `10`           | `[00000000 00000000 0000000 00001][010]` |
| LineTo    | `2`  | `3`   | `26`           | `[00000000 00000000 0000000 00011][010]` |
| ClosePath | `7`  | `1`   | `15`           | `[00000000 00000000 0000000 00001][111]` |


#### 4.3.2. Parameter Integers

Commands requiring parameters are followed by a `ParameterInteger` for each parameter required by that command. The number of `ParameterIntegers` that follow a `CommandInteger` is equal to the parameter count of a command multiplied by the command count of the `CommandInteger`. For example, a `CommandInteger` with a `MoveTo` command with a command count of 3 will be followed by 6 `ParameterIntegers`.

A `ParameterInteger` is [zigzag](https://developers.google.com/protocol-buffers/docs/encoding#types) encoded so that small negative and positive values are both encoded as small integers. To encode a parameter value to a `ParameterInteger` the following formula is used:

```javascript
ParameterInteger = (value << 1) ^ (value >> 31)
```

Parameter values greater than `pow(2,31) - 1` or less than `-1 * (pow(2,31) - 1)` are not supported.

The following formula is used to decode a `ParameterInteger` to a value:

```javascript
value = ((ParameterInteger >> 1) ^ (-(ParameterInteger & 1)))
```

#### 4.3.3. Command Types

For all descriptions of commands the initial position of the cursor shall be described to be at the coordinates `(cX, cY)` where `cX` is the position of the cursor on the X axis and `cY` is the position of the `cursor` on the Y axis.

##### 4.3.3.1. MoveTo Command

A `MoveTo` command with a command count of `n` MUST be immediately followed by `n` pairs of `ParameterInteger`s. Each pair `(dX, dY)`:

1. Defines the coordinate `(pX, pY)`, where `pX = cX + dX` and `pY = cY + dY`.
   * Within POINT geometries, this coordinate defines a new point.
   * Within LINESTRING geometries, this coordinate defines the starting vertex of a new line.
   * Within POLYGON geometries, this coordinate defines the starting vertex of a new linear ring.
2. Moves the cursor to `(pX, pY)`.

#### 4.3.3.2. LineTo Command

A `LineTo` command with a command count of `n` MUST be immediately followed by `n` pairs of `ParameterInteger`s. Each pair `(dX, dY)`:

1. Defines a segment beginning at the cursor `(cX, cY)` and ending at the coordinate `(pX, pY)`, where `pX = cX + dX` and `pY = cY + dY`.
   * Within LINESTRING geometries, this segment extends the current line.
   * Within POLYGON geometries, this segment extends the current linear ring.
2. Moves the cursor to `(pX, pY)`.

For any pair of `(dX, dY)` the `dX` and `dY` MUST NOT both be `0`.

#### 4.3.3.3. ClosePath Command

A `ClosePath` command MUST have a command count of 1 and no parameters. The command closes the current linear ring of a POLYGON geometry via a line segment beginning at the cursor `(cX, cY)` and ending at the starting vertex of the current linear ring.

This command does not change the cursor position.

#### 4.3.4. Geometry Types

The `geometry` field is described in each feature by the `type` field which must be a value in the enum `GeomType`. The following geometry types are supported:

* UNKNOWN
* POINT
* LINESTRING
* POLYGON

Geometry collections are not supported.

##### 4.3.4.1. Unknown Geometry Type

The specification purposefully leaves an unknown geometry type as an option. This geometry type encodes experimental geometry types that an encoder MAY choose to implement. Decoders MAY ignore any features of this geometry type.

##### 4.3.4.2. Point Geometry Type

The `POINT` geometry type encodes a point or multipoint geometry. The geometry command sequence for a point geometry MUST consist of a single `MoveTo` command with a command count greater than 0.

If the `MoveTo` command for a `POINT` geometry has a command count of 1, then the geometry MUST be interpreted as a single point; otherwise the geometry MUST be interpreted as a multipoint geometry, wherein each pair of `ParameterInteger`s encodes a single point.

##### 4.3.4.3. Linestring Geometry Type

The `LINESTRING` geometry type encodes a linestring or multilinestring geometry. The geometry command sequence for a linestring geometry MUST consist of one or more repetitions of the following sequence: 

1. A `MoveTo` command with a command count of 1
2. A `LineTo` command with a command count greater than 0

If the command sequence for a `LINESTRING` geometry type includes only a single `MoveTo` command then the geometry MUST be interpreted as a single linestring; otherwise the geometry MUST be interpreted as a multilinestring geometry, wherein each `MoveTo` signals the beginning of a new linestring.

##### 4.3.4.4. Polygon Geometry Type

The `POLYGON` geometry type encodes a polygon or multipolygon geometry, each polygon consisting of exactly one exterior ring that contains zero or more interior rings. The geometry command sequence for a polygon consists of one or more repetitions of the following sequence:

1. An `ExteriorRing`
2. Zero or more `InteriorRing`s

Each `ExteriorRing` and `InteriorRing` MUST consist of the following sequence:

1. A `MoveTo` command with a command count of 1
2. A `LineTo` command with a command count greater than 1
3. A `ClosePath` command

An exterior ring is DEFINED as a linear ring having a positive area as calculated by applying the [surveyor's formula](https://en.wikipedia.org/wiki/Shoelace_formula) to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the exterior ring's winding order appear clockwise.

An interior ring is DEFINED as a linear ring having a negative area as calculated by applying the [surveyor's formula](https://en.wikipedia.org/wiki/Shoelace_formula) to the vertices of the polygon in tile coordinates. In the tile coordinate system (with the Y axis positive down and X axis positive to the right) this makes the interior ring's winding order appear counterclockwise.

If the command sequence for a `POLYGON` geometry type includes only a single exterior ring then the geometry MUST be interpreted as a single polygon; otherwise the geometry MUST be interpreted as a multipolygon geometry, wherein each exterior ring signals the beginning of a new polygon. If a polygon has interior rings they MUST be encoded directly after the exterior ring of the polygon to which they belong.

Linear rings MUST be geometric objects that have no anomalous geometric points, such as self-intersection or self-tangency. The position of the cursor before calling the `ClosePath` command of a linear ring SHALL NOT repeat the same position as the first point in the linear ring as this would create a zero-length line segment. A linear ring SHOULD NOT have an area calculated by the surveyor's formula equal to zero, as this would signify a ring with anomalous geometric points.

Polygon geometries MUST NOT have any interior rings that intersect and interior rings MUST be enclosed by the exterior ring.

#### 4.3.5. Example Geometry Encodings

##### 4.3.5.1. Example Point

An example encoding of a point located at:

* (25,7)

This would require a single command:

* MoveTo(+25, +17)

```
Encoded as: [ 9 50 34 ]
              | |  `> Decoded: ((34 >> 1) ^ (-(34 & 1))) = +17
              | `> Decoded: ((50 >> 1) ^ (-(50 & 1))) = +25
              | ===== relative MoveTo(+25, +17) == create point (25,17)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.2. Example Multi Point

An example encoding of two points located at:

* (5,7)
* (3,2)

This would require two commands:

* MoveTo(+5,+7)
* MoveTo(-2,-5)

```
Encoded as: [ 17 10 14 3 9 ]
               |  |  | | `> Decoded: ((9 >> 1) ^ (-(9 & 1))) = -5
               |  |  | `> Decoded: ((3 >> 1) ^ (-(3 & 1))) = -2
               |  |  | === relative MoveTo(-2, -5) == create point (3,2)
               |  |  `> Decoded: ((34 >> 1) ^ (-(34 & 1))) = +7
               |  `> Decoded: ((50 >> 1) ^ (-(50 & 1))) = +5
               | ===== relative MoveTo(+25, +17) == create point (25,17)
               `> [00010 001] = command id 1 (MoveTo), length 2
```

##### 4.3.5.3. Example Linestring

An example encoding of a line with the points:

* (2,2)
* (2,10)
* (10,10)

This would require three commands:

* MoveTo(+2,+2)
* LineTo(+0,+8)
* LineTo(+8,+0)

```
Encoded as: [ 9 4 4 18 0 16 16 0 ]
              |      |      ==== relative LineTo(+8, +0) == Line to Point (10, 10)
              |      | ==== relative LineTo(+0, +8) == Line to Point (2, 10)
              |      `> [00010 010] = command id 2 (LineTo), length 2
              | === relative MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.4. Example Multi Linestring

An example encoding of two lines with the points:

* Line 1:
  * (2,2)
  * (2,10)
  * (10,10)
* Line 2:
  * (1,1)
  * (3,5)

This would require the following commands:

* MoveTo(+2,+2)
* LineTo(+0,+8)
* LineTo(+8,+0)
* MoveTo(-9,-9)
* LineTo(+2,+4)

```
Encoded as: [ 9 4 4 18 0 16 16 0 9 17 17 10 4 8 ]
              |      |           |        | === relative LineTo(+2, +4) == Line to Point (3,5)
              |      |           |        `> [00001 010] = command id 2 (LineTo), length 1
              |      |           | ===== relative MoveTo(-9, -9) == Start new line at (1,1)
              |      |           `> [00001 001] = command id 1 (MoveTo), length 1
              |      |      ==== relative LineTo(+8, +0) == Line to Point (10, 10)
              |      | ==== relative LineTo(+0, +8) == Line to Point (2, 10)
              |      `> [00010 010] = command id 2 (LineTo), length 2
              | === relative MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.5. Example Polygon

An example encoding of a polygon feature that has the points:

* (3,6)
* (8,12)
* (20,34)
* (3,6) *Path Closing as Last Point*

Would encoded by using the following commands:

* MoveTo(3, 6)
* LineTo(5, 6)
* LineTo(12, 22)
* ClosePath

```
Encoded as: [ 9 6 12 18 10 12 24 44 15 ]
              |       |              `> [00001 111] command id 7 (ClosePath), length 1
              |       |       ===== relative LineTo(+12, +22) == Line to Point (20, 34)
              |       | ===== relative LineTo(+5, +6) == Line to Point (8, 12)
              |       `> [00010 010] = command id 2 (LineTo), length 2
              | ==== relative MoveTo(+3, +6)
              `> [00001 001] = command id 1 (MoveTo), length 1
```

##### 4.3.5.6. Example Multi Polygon

An example of a more complex encoding of two polygons, one with a hole. The position of the points for the polygons are shown below. The winding order of the polygons is VERY important in this example as it signifies the difference between interior rings and a new polygon.

* Polygon 1:
  * Exterior Ring:
    * (0,0)
    * (10,0)
    * (10,10)
    * (0,10)
    * (0,0) *Path Closing as Last Point*
* Polygon 2:
  * Exterior Ring:
    * (11,11)
    * (20,11)
    * (20,20)
    * (11,20)
    * (11,11) *Path Closing as Last Point*
  * Interior Ring:
    * (13,13)
    * (13,17)
    * (17,17)
    * (17,13)
    * (13,13) *Path Closing as Last Point*

This polygon would be encoded with the following set of commands:

* MoveTo(+0,+0)
* LineTo(+10,+0)
* LineTo(+0,+10)
* LineTo(-10,+0) // Cursor at 0,10 after this command
* ClosePath // End of Polygon 1
* MoveTo(+11,+1) // NOTE THAT THIS IS RELATIVE TO LAST LINETO!
* LineTo(+9,+0)
* LineTo(+0,+9)
* LineTo(-9,+0) // Cursor at 11,20 after this command
* ClosePath // This is a new polygon because area is positive!
* MoveTo(+2,-7) // NOTE THAT THIS IS RELATIVE TO LAST LINETO!
* LineTo(+0,+4)
* LineTo(+4,+0)
* LineTo(+0,-4) // Cursor at 17,13
* ClosePath // This is an interior ring because area is negative!

### 4.4. Feature Attributes

Feature attributes are encoded as pairs of integers in the `tag` field of a feature. The first integer in each pair represents the zero-based index of the key in the `keys` set of the `layer` to which the feature belongs. The second integer in each pair represents the zero-based index of the value in the `values` set of the `layer` to which the feature belongs. Every key index MUST be unique within that feature such that no other attribute pair within that feature has the same key index. A feature MUST have an even number of `tag` fields. A feature `tag` field MUST NOT contain a key index or value index greater than or equal to the number of elements in the layer's `keys` or `values` set, respectively.

### 4.5. Example

For example, a GeoJSON feature like:

```json
{
    "type": "FeatureCollection",
    "features": [
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -8247861.1000836585,
                    4970241.327215323
                ]
            },
            "type": "Feature",
            "properties": {
                "hello": "world",
                "h": "world",
                "count": 1.23
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -8247861.1000836585,
                    4970241.327215323
                ]
            },
            "type": "Feature",
            "properties": {
                "hello": "again",
                "count": 2
            }
        }
    ]
}
```

Could be structured like:

```js
layers {
  version: 2
  name: "points"
  features: {
    id: 1
    tags: 0
    tags: 0
    tags: 1
    tags: 0
    tags: 2
    tags: 1
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  features {
    id: 1
    tags: 0
    tags: 2
    tags: 2
    tags: 3
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  keys: "hello"
  keys: "h"
  keys: "count"
  values: {
    string_value: "world"
  }
  values: {
    double_value: 1.23
  }
  values: {
    string_value: "again"
  }
  values: {
    int_value: 2
  }
  extent: 4096
}
```

Keep in mind the exact values for the geometry would differ based on the projection and extent of the tile.


================================================
FILE: 2.1/README_zh.md
================================================
# 矢量瓦片标准

本文档中的“**必须**”、“**必须不**”、“**必备**”、"**应该**"、“**不应该**”、“**建议**”、“**可以**”、“**可选**”的含义参照[RFC 2119](https://www.ietf.org/rfc/rfc2119.txt)。

## 1. 目标

本文档规定了一种节省存储空间的矢量瓦片数据编码格式。这种格式应用于客户端或服务端高效渲染或查询要素信息。

## 2. 文件格式

矢量瓦片文件采用[Google Protocol Buffers](https://developers.google.com/protocol-buffers/)进行编码。Google Protocol Buffers是一种兼容多语言、多平台、易扩展的数据序列化格式。

### 2.1. 文件后缀

矢量瓦片文件的后缀**应该**为`mvt`。例如,`vector.mvt`。

### 2.2 MIME类型

矢量瓦片的MIME类型**应该**设置为`application/vnd.mapbox-vector-tile`。

## 3. 投影和范围

矢量瓦片表示的是投影在正方形区块上的数据。矢量瓦片**不应该**包含范围和投影信息。解码方被假定知道矢量瓦片的范围和投影信息。

[Web Mercator](https://en.wikipedia.org/wiki/Web_Mercator)是默认的投影方式,[Google tile scheme](http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/)是默认的瓦片编号方式。两者一起完成了与任意范围、任意精度的地理区域的一一对应,例如`https://example.com/17/65535/43602.mvt`。

矢量瓦片**可以**用来表示任意投影方式、任意瓦片编号方案的数据。

## 4. 内部结构

这部分内容描述矢量瓦片的数据结构。读者需要先了解[矢量瓦片protobuf编码方案文件](https://github.com/mapbox/vector-tile-spec/blob/master/2.1%2Fvector_tile.proto)中的结构定义。

### 4.1. 图层

矢量瓦片由一组命名的图层构成。每个图层包含几何要素和元数据信息。设计的图层格式能够保证图层数据能够在内存中按顺序排列,由此在图层组末尾添加一个新的图层就不用更改已有的数据。

每块矢量瓦片**应该**至少包含一个图层。每个图层**应该**至少包含一个要素。

图层**必须**包含一个`version`字段表示此图层所遵守的《矢量瓦片标准》的主版本号。例如,某个图层遵守2.1版本的标准,那么它的`version`字段的值则为整数`2`。`version`字段**应该**设定为图层的第一个字段。解码器**应该**首先解析`version`字段,以确定是否能够解析该版本的图层。当遇到一个未知版本的矢量瓦片图层时,解码器**可以**尝试去解析它,或者**可以**跳过该图层。以上两种情况下,解码器都**应该**继续解析后续的图层。

图层**必须**包含一个`name`字段。每块矢量瓦片**必须不**包含两个或两个以上的图层具有相同`name`值。在向一块矢量瓦片添加一个新的图层之前,编码器**必须**检查已有的`name`值以防止重复。

图层中的每个要素**可以**包含一个或多个key-value作为它的元数据(见下文)。所有要素的key和value被分别索引为两个列表——`keys`和`values`——为图层中的所有要素所共享。

图层`keys`字段的每个元素都是字符串。`keys`字段包含了图层中所有要素的key,并且每个key可以通过它在`keys`列表中的索引号引用,第一个key的索引号是0 。`keys`列表**必须不**包含两个或两个以上key是一样的。

图层`values`字段的每个元素是多种类型的值的编码(见下文)。`values`字段包含了图层中所有要素的value,并且每个value可以通过它在`values`列表中的索引号引用,第一个value的索引号是0 。`values`列表**必须不**包含两个或两个以上value是一样的。

为了支持字符串型、布尔型、整型、浮点型多种类型的值,对`value`字段的编码包含了一组`optional`字段。每个value**必须**包含其中的一个字段。

图层**必须**包含一个`extent`字段,表示瓦片的宽度和高度,以整数表示。矢量瓦片中的几何坐标**可以**超出`extent`定义的范围。超出`extent`范围的几何要素被经常用来作为缓冲区,以渲染重叠在多块相邻瓦片上的要素。

例如,如果一块瓦片的`extent`范围是4096,那么坐标的单位是瓦片长宽的1/4096。坐标0在瓦片的顶部或左边缘,坐标4096在瓦片的底部或右边缘。坐标从1到4095都是在瓦片内部,坐标小于0或者大于4096在瓦片外部。坐标`(1,10)`或`(4095,10)`在瓦片内部。坐标`(0,10)`或`(4096,10)`在瓦片边缘。坐标`(-1,10)`或`(4097,10)`在瓦片外部。

### 4.2. 要素

每个要素**必须**包含一个`geometry`字段。

每个要素**必须**包含一个`type`字段,该字段将在几何类型章节描述(4.3.4)。

每个要素**可以**包含一个`tags`字段。如果存在属于要素级别的元数据,**应该**存储到`tags`字段中。

每个要素**可以**包含一个`id`字段。如果一个要素包含一个`id`字段,那么`id`字段的值**应该**相对于图层中的其他要素是唯一的。

### 4.3. 几何图形编码

矢量瓦片中的几何数据被定义为屏幕坐标系。瓦片的左上角(显示默认如此)是坐标系的原点。X轴向右为正,Y轴向下为正。几何图形中的坐标**必须**为整数。

几何图形被编码为要素的`geometry`字段的一个32位无符号型整数序列。每个整数是`CommandInteger`或者`ParameterInteger`。解码器解析这些整数序列作为生成几何图形的一系列有序操作。

指令涉及到的位置是相对于“游标”的,即一个可重定义的点。对于要素中的第一条指令,游标在坐标系中的位置是`(0,0)`。有些指令能够移动游标,因而会影响到接下来执行的指令。

#### 4.3.1. 指令数

`CommandInteger`指代所要执行的操作和执行的次数,分别以command ID和command count表示。

command ID以`CommandInteger`最末尾的3个比特位表示,即从0到7。command count以`CommandInteger`剩下的29个比特位表示,即`0`到`pow(2, 29) - 1`。

command ID、command count、和`CommandInteger`三者可以通过以下位运算相互转换。

```javascript
CommandInteger = (id & 0x7) | (count << 3)
```

```javascript
id = CommandInteger & 0x7
```

```javascript
count = CommandInteger >> 3
```

每个command ID表示以下指令中的一种:

|  指令        |  Id  | 参数          | 参数个数        |
| ------------ |:----:| ------------- | --------------- |
| MoveTo       | `1`  | `dX`, `dY`    | 2               |
| LineTo       | `2`  | `dX`, `dY`    | 2               |
| ClosePath    | `7`  | 无参数        | 0               |

##### 指令数示例

| 指令      |  ID  | Count | CommandInteger | 二进制表示`[Count][Id]`                  |
| --------- |:----:|:-----:|:--------------:|:----------------------------------------:|
| MoveTo    | `1`  | `1`   | `9`            | `[00000000 00000000 0000000 00001][001]` |
| MoveTo    | `1`  | `120` | `961`          | `[00000000 00000000 0000011 11000][001]` |
| LineTo    | `2`  | `1`   | `10`           | `[00000000 00000000 0000000 00001][010]` |
| LineTo    | `2`  | `3`   | `26`           | `[00000000 00000000 0000000 00011][010]` |
| ClosePath | `7`  | `1`   | `15`           | `[00000000 00000000 0000000 00001][111]` |


#### 4.3.2. 参数数

指令的所有参数紧跟在`ParameterInteger`之后。跟在`CommandInteger`之后的`ParameterIntegers`个数等于指令所需要参数的个数乘以指令执行的次数。例如,一条指示`MoveTo`指令执行3次的`CommandInteger`之后会跟随6个`ParameterIntegers`。

`ParameterInteger`由[zigzag](https://developers.google.com/protocol-buffers/docs/encoding#types)方式编码得到,以使小负数和正数都被编码为小整数。将参数值编码为`ParameterInteger`按以下公式转换:

```javascript
ParameterInteger = (value << 1) ^ (value >> 31)
```

参数值不支持大于`pow(2,31) - 1`或`-1 * (pow(2,31) - 1)`的数值。

以下的公式用来将`ParameterInteger`解码为实际值:

```javascript
value = ((ParameterInteger >> 1) ^ (-(ParameterInteger & 1)))
```

#### 4.3.3. 指令类型

以下关于指令的描述中,游标的初始位置定义为坐标`(cX, cY)`,其中`cX`指代游标在X轴上的位置,`cY`指代游标在Y轴上的位置。

##### 4.3.3.1. MoveTo指令

表示`MoveTo`指令执行`n`的`ParameterInteger`**必须**立即接上`n`对`ParameterInteger`。对于`(dX, dY)`参数:

1. 定义坐标`(pX, pY)`,其中`pX = cX + dX`和`pY = cY + dY`。
   * 对于点要素,这个坐标定义了一个新的点要素。
   * 对于线要素,这个坐标定义了一条新的线要素的起点。
   * 对于面要素,这个坐标定义了一个新环的起点。
2. 将游标移至`(pX, pY)`。

##### 4.3.3.1. LineTo指令

表示`LineTo`指令执行`n`的`ParameterInteger`**必须**立即接上`n`对`ParameterInteger`。对于`(dX, dY)`参数:

1. 定义一条以游标位置`(cX, cY)`为起点,`(pX, pY)`为终点的线段,其中`pX = cX + dX`和`pY = cY + dY`。
   * 对于线要素,这条线段延长了当前线要素。
   * 对于面要素,这条线段延长了当前环。
2. 将游标移至`(pX, pY)`。

对于任意一对`(dX, dY)`,`dX`和`dY`**必须不**能同时为`0`.

#### 4.3.3.3. ClosePath指令

每条`ClosePath`指令**必须**只能执行一次并且无附带参数。这条指令通过构造一条以游标`(cX, cY)`为起点、当前环的起点为终点的线段,闭合面要素的当前环。

这条指令不改变游标的位置。

#### 4.3.4. 几何类型

要素`geometry`字段的`type`的取值**必须**是`GeomType`枚举值之一。支持的几何类型如下:

* UNKNOWN
* POINT
* LINESTRING
* POLYGON

不支持`GeometryCollection`类型。

##### 4.3.4.1. Unknown几何类型

本标准有意设置一个Unknown几何类型。这种几何类型**可以**用来编码试验性的几何类型。解码器**可以**选择忽略这种几何类型的要素。

##### 4.3.4.2. Point几何类型

`POINT`几何类型用来表示单点或多点几何。每个点几何的指令序列**必须**包含一个`MoveTo`指令,并且该指令的command count大于0。

如果`POINT`几何的`MoveTo`的command count为1,那么**必须**将其解析为单点;否则**必须**解析为多点,指令后面的每对`ParameterInteger`表示一个单点。

##### 4.3.4.3. Linestring几何类型

`LINESTRING`几何类型用来表示单线或多线几何。线几何的指令序列**必须**包含一个或多个下列序列:

1. 一个`MoveTo`指令,其command count为1
2. 一个`LineTo`指令,其command count大于0

如果`LINESTRING`的指令序列只包含1个`MoveTo`指令,那么**必须**将其解析为单线;否则,**必须**将其解析为多线,其中的每个`MoveTo`指令开始构造一条新线几何。

##### 4.3.4.4. Polygon几何类型

`POLYGON`几何类型表示面或多面几何,每个面有且只有一个外环和零个或多个内环。面几何的指令序列包含一个或多个下列序列:

1. 一个`ExteriorRing`
2. 零个或多个`InteriorRing`

Each `ExteriorRing` and `InteriorRing` MUST consist of the following sequence:
每个`ExteriorRing`和`InteriorRing`必须包含以下序列:

1. 一个`MoveTo`指令,其command count为1
2. 一个`LineTo`指令,其command count大于1
3. 一个`ClosePath`指令

一个外环被**定义**为一个线性的环,当应用[surveyor's formula](https://en.wikipedia.org/wiki/Shoelace_formula),以多边形的节点在瓦片坐标系下的坐标计算面积时,其面积为正。在瓦片坐标系下(X向右为正,Y向下为正),外环节点以顺时针旋转。

一个内环被**定义**为一个线性的环,当应用[surveyor's formula](https://en.wikipedia.org/wiki/Shoelace_formula),以多边形的节点在瓦片坐标系下的坐标计算面积时,其面积为负。在瓦片坐标系下(X向右为正,Y向下为正),内环节点以逆时针旋转。

如果`POLYGON`的指令序列只包含一个外环,那么**必须**将其解析为单面;否则,**必须**解析为多面几何,其中每个外环表示一个新面的开始。如果面几何包换内环,那么**必须**将其编码到所属的外环之后。

线性环**必须**不包含异常点,例如自相交或自相切。在`ClosePath`之前的坐标**不应该**与线性环的起始点坐标相同,因为会产生零长度的线段。线性环经过surveyor's formula计算的面积**不应该**为0,因为这意味着环包含有异常点。

面几何**必须不**能有内环相交,并且内环**必须**被包围在内环之中。

#### 4.3.5. 几何要素编码示例

##### 4.3.5.1. 点要素示例

假设示例点的坐标为:

* (25, 17)

表示它只需要一条指令:

* MoveTo(+25, +17)

```bash
编码      : [ 9 50 34 ]
              | |  `> 解码: ((34 >> 1) ^ (-(34 & 1))) = +17
              | `> 解码: ((50 >> 1) ^ (-(50 & 1))) = +25
              | ===== 相对地 MoveTo(+25, +17) == 创建点 (25,17)
              `> [00001 001] = command id 1 (MoveTo), command count 1
```

##### 4.3.5.2. 多点要素示例

假设多点要素的坐标为:

* (5,7)
* (3,2)

编码需要两条指令:

* MoveTo(+5,+7)
* MoveTo(-2,-5)

```bash
编码      : [ 17 10 14 3 9 ]
               |  |  | | `> 解码: ((9 >> 1) ^ (-(9 & 1))) = -5
               |  |  | `> 解码: ((3 >> 1) ^ (-(3 & 1))) = -2
               |  |  | === 相对地 MoveTo(-2, -5) == 创建点 (3,2)
               |  |  `> 解码: ((34 >> 1) ^ (-(34 & 1))) = +7
               |  `> 解码: ((50 >> 1) ^ (-(50 & 1))) = +5
               | ===== 相对地 MoveTo(+5, +7) == 创建点 (5,7)
               `> [00010 001] = command id 1 (MoveTo), command count 2
```

##### 4.3.5.3. 线要素示例

假设示例线要素的坐标为:

* (2,2)
* (2,10)
* (10,10)

编码需要3条指令:

* MoveTo(+2,+2)
* LineTo(+0,+8)
* LineTo(+8,+0)

```bash
编码      : [ 9 4 4 18 0 16 16 0 ]
              |      |      ==== 相对地 LineTo(+8, +0) == 连接到点 (10, 10)
              |      | ==== 相对地 LineTo(+0, +8) == 连接到点 (2, 10)
              |      `> [00010 010] = command id 2 (LineTo), command count 2
              | === 相对地 MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), command count 1
```

##### 4.3.5.4. Example Multi Linestring
##### 4.3.5.4. 多线要素示例

假设示例要素的坐标为:

* Line 1:
  * (2,2)
  * (2,10)
  * (10,10)
* Line 2:
  * (1,1)
  * (3,5)

编码需要以下指令:

* MoveTo(+2,+2)
* LineTo(+0,+8)
* LineTo(+8,+0)
* MoveTo(-9,-9)
* LineTo(+2,+4)

```bash
编码      : [ 9 4 4 18 0 16 16 0 9 17 17 10 4 8 ]
              |      |           |        | === 相对地 LineTo(+2, +4) == 连接到点 (3,5)
              |      |           |        `> [00001 010] = command id 2 (LineTo), command count 1
              |      |           | ===== 相对地 MoveTo(-9, -9) == 新建一条线从 (1,1)
              |      |           `> [00001 001] = command id 1 (MoveTo), command count 1
              |      |      ==== 相对地 LineTo(+8, +0) == 连接到点 (10, 10)
              |      | ==== 相对地 LineTo(+0, +8) == 连接到点 (2, 10)
              |      `> [00010 010] = command id 2 (LineTo), command count 2
              | === 相对地 MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), command count 1
```

##### 4.3.5.5. 面要素示例

假设示例面要素的坐标为:

* (3,6)
* (8,12)
* (20,34)
* (3,6) *闭合*

编码需要以下指令:

* MoveTo(3, 6)
* LineTo(5, 6)
* LineTo(12, 22)
* ClosePath

```bash
编码      : [ 9 6 12 18 10 12 24 44 15 ]
              |       |              `> [00001 111] command id 7 (ClosePath), command count 1
              |       |       ===== 相对地 LineTo(+12, +22) == 连接到点 (20, 34)
              |       | ===== 相对地 LineTo(+5, +6) == 连接到点 (8, 12)
              |       `> [00010 010] = command id 2 (LineTo), command count 2
              | ==== 相对地 MoveTo(+3, +6)
              `> [00001 001] = command id 1 (MoveTo), command count 1
```

##### 4.3.5.6. 多面要素示例

示例要素包含两个多边形,其中一个多边形有一个洞。多边形中的点如下。注意,多边形中的点环绕顺序**非常**重要,应为这个顺序被用来区别外环和内环。

* Polygon 1:
  * 外环:
    * (0,0)
    * (10,0)
    * (10,10)
    * (0,10)
    * (0,0) *闭合*
* Polygon 2:
  * 外环:
    * (11,11)
    * (20,11)
    * (20,20)
    * (11,20)
    * (11,11) *闭合*
  * 内环:
    * (13,13)
    * (13,17)
    * (17,17)
    * (17,13)
    * (13,13) *闭合*

编码需要以下一系列指令:

* MoveTo(+0,+0)
* LineTo(+10,+0)
* LineTo(+0,+10)
* LineTo(-10,+0) // 执行这条指令后,游标的位置在(0, 10)
* ClosePath // Polygon 1结束
* MoveTo(+11,+1) // **这条指令相对于上面最后一条LineTo指令!**
* LineTo(+9,+0)
* LineTo(+0,+9)
* LineTo(-9,+0) // 执行这条指令后,游标的位置在(11, 20)
* ClosePath // 这是一个新面要素,因为面积为正
* MoveTo(+2,-7) // **这条指令相对于上面最后一条LineTo指令!**
* LineTo(+0,+4)
* LineTo(+4,+0)
* LineTo(+0,-4) // 执行这条指令后,游标的位置在(17, 13)
* ClosePath // 这是一个内环,因为面积为负

### 4.4. 要素属性

要素属性被编码为`tag`字段中的一对对整数。在每对`tag`中,第一个整数表示key在其所属的`layer`的`keys`列表的中索引号(以0开始)。第二个整数表示value在其所属的`layer`的`values`列表的中索引号(以0开始)。一个要素的所有key索引**必须唯一**,以保证要素中没有重复的属性项。每个要素的`tag`字段**必须**为偶数。要素中的`tag`字段包含的key索引号或value索引号**必须不**能大于或等于相应图层中`keys`或`values`列表中的元素数目。

### 4.5. 示例

例如,一个GeoJSON格式的要素如下:

```json
{
    "type": "FeatureCollection",
    "features": [
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -8247861.1000836585,
                    4970241.327215323
                ]
            },
            "type": "Feature",
            "properties": {
                "hello": "world",
                "h": "world",
                "count": 1.23
            }
        },
        {
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -8247861.1000836585,
                    4970241.327215323
                ]
            },
            "type": "Feature",
            "properties": {
                "hello": "again",
                "count": 2
            }
        }
    ]
}
```

会被结构化为:

```js
layers {
  version: 2
  name: "points"
  features: {
    id: 1
    tags: 0
    tags: 0
    tags: 1
    tags: 0
    tags: 2
    tags: 1
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  features {
    id: 2
    tags: 0
    tags: 2
    tags: 2
    tags: 3
    type: Point
    geometry: 9
    geometry: 2410
    geometry: 3080
  }
  keys: "hello"
  keys: "h"
  keys: "count"
  values: {
    string_value: "world"
  }
  values: {
    double_value: 1.23
  }
  values: {
    string_value: "again"
  }
  values: {
    int_value: 2
  }
  extent: 4096
}
```

注意几何要素的实际坐标取决于坐标系和瓦片的范围。


================================================
FILE: 2.1/vector_tile.proto
================================================
// Protocol Version 1

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;
        }

        // Variant type encoding
        // The use of values is described in section 4.1 of the specification
        message Value {
                // Exactly one of these values must be present in a valid message
                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;

                extensions 8 to max;
        }

        // Features are described in section 4.2 of the specification
        message Feature {
                optional uint64 id = 1 [ default = 0 ];

                // 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 on geometry encoding is located in 
                // section 4.3 of the specification.
                repeated uint32 geometry = 4 [ packed = true ];
        }

        // 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;
}


================================================
FILE: CHANGELOG.md
================================================
# Vector Tile Spec Changelog

### 2.1

The 2.1 update of the specification is a correction to the wording in a few locations of the 2.0 specification. The wording of the specification is slightly changed in 2.1, but reflects important concepts that were improperly described by the 2.0 specification. 

#### Summary of Changes:

 - Changed the meaning of `extent` to reflect how all known implementations of the specification use extent.
 - Changed the wording to make it such that `LineTo(0,0)` is an invalid command by changing wording from SHOULD to MUST.
 - Added `CONTRIBUTING.md` file

#### Issues:

 List of issues addressed by this version:

 - [#54](https://github.com/mapbox/vector-tile-spec/issues/54) 
 - [#51](https://github.com/mapbox/vector-tile-spec/issues/51) 

#### Date of Release:

January 19th, 2016

### 2.0

The focus of version `2.0` of the Mapbox Vector Tile specification is the clarification of the intent of the intial version of the specification and the definition of interior and exterior rings within polygons. The fields within the protobuffer are more clearly defined in this version of the specification and the steps for decoders and encoders are more explicity declared. 

The version numbering of the specification is now more clearly defined as well as part of the `2.0` changes, migrating from a `major.minor.patch` versioning to a `major.minor` versioning. 

Sections to the specification have been introduced to improve readablility. There are now more examples of the geometry encoding process to ease understanding of the concepts within the specification.

The file [CONTRIBUTING.md] has been added to the repository to better define a repeatable process for changing the specification.

#### Summary of Changes:

 - Clarification of how polygon exterior and interior rings should be oriented and ordered: If present, any polygon interior rings (holes) must be oriented with the opposite winding order than their parent exterior rings and all interior rings must directly follow the exterior ring they belong too. Exterior rings must be oriented CW and interior rings must be oriented CCW (when viewed in screen coordinates).
 - Noted that first point does not have to be the same as last point prior to calling `ClosePath`.
 - Polygon geometries now must not have self intersections or self tangency. (Example: spikes in rings)
 - Addded definition of linear ring.
 - Clarified that `UNKNOWN` geometry types may be ignored and that it is experimental.
 - Required the use of the `version` field in layers.
 - Required that layers of a tile not have the same `name` field as any other layer.
 - Explained differences between geometry types.
 - Added explanation of how to handle multipoint, multilines, and multipolygons geometries.
 - Migrated the encoding logic from `proto` file to the README, adding many clarifications.
 - Explained the different commands used in encoding.
 - Added the concept of the `cursor` when encoding and decoding a vector tile.
 - Explained the coordinate system of a vector tile.
 - Made it clear that specification could be used in projections other than Mercator.
 - Defined more clearly feature attributes and how they are handled.
 - `LineTo` command should not resolve to same position - ex: `LineTo(0,0)`.
 - Changed the way that versioning of the specification is handled. 
 - Updated Authors
 - Added `CONTRIBUTING.md` file

#### Issues:

 List of issues addressed by this version:

 - [#43](https://github.com/mapbox/vector-tile-spec/issues/43) 
 - [#41](https://github.com/mapbox/vector-tile-spec/issues/41) 
 - [#30](https://github.com/mapbox/vector-tile-spec/issues/30) 
 - [#29](https://github.com/mapbox/vector-tile-spec/issues/29) 
 - [#27](https://github.com/mapbox/vector-tile-spec/issues/27) 
 - [#25](https://github.com/mapbox/vector-tile-spec/issues/25) 
 - [#24](https://github.com/mapbox/vector-tile-spec/issues/24) 
 - [#18](https://github.com/mapbox/vector-tile-spec/issues/18) 
 - [#16](https://github.com/mapbox/vector-tile-spec/issues/16) 
 - [#15](https://github.com/mapbox/vector-tile-spec/issues/15) 
 - [#7](https://github.com/mapbox/vector-tile-spec/issues/7) 
 - [#5](https://github.com/mapbox/vector-tile-spec/issues/5) 

#### Date of Release:

December 4th, 2015

### 1.0.1

 - Used TitleCase and UPPERCASE in `vector_tile.proto` to match Protobuf style guide (#3)
 - Changed namespace from `mapnik.vector` to `vector_tile` (#2)

### 1.0.0

 - First release


================================================
FILE: CONTRIBUTING.md
================================================
## Open Standard

The Mapbox Vector Tile specification is an open standard maintained by [Mapbox](https://www.mapbox.com/about/open/).

## Questions and Contributing

All specification development happens at the [github repository for the specification](https://github.com/mapbox/vector-tile-spec).

For general questions relating to the specification please feel free to create a new [issue](https://github.com/mapbox/vector-tile-spec/issues).

### Proposing Changes

Editorial changes that clarify the specification are encouraged. Edits can be submitted as a pull request to against the `master` branch of the latest version of the specification. Review and discussion of the proposed changes will take place on this pull request. Changes may warrant a bump in the `minor` version of the specification.

Technical changes to the specification are an important part of the evolution of the standard. Technical changes imply new requirements for encoders and decoders of the format. Therefore a technical change requires the `major` version to be incremented and will be carefully reviewed and considered by implementors of the specification. Technical changes are best discussed in individual [issues](https://github.com/mapbox/vector-tile-spec/issues) prior to a change in the specification. Please be concise in any suggestions and read existing issues prior to posting.

### Syntax Notes

Consideration should be taken over the uses of the keywords as described in [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt). The use of these words must be capitalized to stress their meaning through out the specification.

The use of fields as defined in the proto file should be `highlighted`.

## Releasing A New Version

The following is the suggested way to release a new version of the specification.

Upon determination that a significant need for a version change is required a pull request to the specification should be opened. The branch from which the pull request originates should be named clearly to note it is a request for a new version of the specification. For example a branch of `v3.0-development` would specify the grouping of changes for the `v3.0` specification. This pull request should create a new folder for the version of the specification that will be created. For the `v3.0` specification a `3.0` folder would be created. Within this folder should be the `proto` file for the version and a `README.md` file that is a full update of the specification. The `CHANGELOG.md` should also include all relevant information on changes that are proposed.

The pull request should provide a clear explanation of the intent for the new version of the specification. All associated issues should be linked in the pull request. Suggested changes to the branch of the development version will be accepted in the form of pull request to that branch.

Once all issues with the pull request have been addressed, the pull request may be merged into the master branch.

Update the changelog with the date of release of the official specification in a new commit to the `master` branch. Push your updates to the repository. Once this is done create an official tag of the release on github.

```sh
git tag -a v2.0 -m "v2.0"
git push --tags
```

## Authors

If you make a change and wish to be added to the list of authors please add yourself to the README.md. (Note: It is alphabetical by last name).



================================================
FILE: README.md
================================================
# Mapbox Vector Tile Specification

A specification for encoding tiled vector data.

## License

The text of this specification is licensed under a
[Creative Commons Attribution 3.0 United States License](http://creativecommons.org/licenses/by/3.0/us/).
However, the use of this spec in products and code is entirely free:
there are no royalties, restrictions, or requirements.

## [Implementations](https://github.com/mapbox/vector-tile-spec/wiki/Implementations)

## Versioning

The specification is versioned based on `major.minor` notation. The `major` version will be incremented with any technical change to the specification format or way it should be interpreted. Changes to the `minor` version will be reserved for any clarification or correction of clerical errors associated with the specification language.

The `major` version in the specification name is synonymous with the `version` field in a Mapbox Vector Tile layer. See the `3.1. Layers` section for more details.


## Contributing

If you are interested in contributing please refer to the [CONTRIBUTING.md](CONTRIBUTING.md) file.

## Authors

* Vladimir Agafonkin
* John Firebaugh
* Eric Fischer
* Konstantin Käfer
* Charlie Loyd
* Tom MacWright
* Artem Pavlenko
* Dane Springmeyer
* Blake Thompson
Download .txt
gitextract_f4e7qftu/

├── 1.0.0/
│   ├── README.md
│   └── vector_tile.proto
├── 1.0.1/
│   ├── README.md
│   └── vector_tile.proto
├── 2.0/
│   ├── README.md
│   └── vector_tile.proto
├── 2.1/
│   ├── README.md
│   ├── README_zh.md
│   └── vector_tile.proto
├── CHANGELOG.md
├── CONTRIBUTING.md
└── README.md
Condensed preview — 12 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (96K chars).
[
  {
    "path": "1.0.0/README.md",
    "chars": 2735,
    "preview": "# vector-tile-spec\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\",\n\"SHOULD\", \"SHOULD NOT\", \"RECOMME"
  },
  {
    "path": "1.0.0/vector_tile.proto",
    "chars": 3943,
    "preview": "// Protocol Version 1\n\npackage mapnik.vector;\n\noption optimize_for = LITE_RUNTIME;\n\nmessage tile {\n        enum GeomType"
  },
  {
    "path": "1.0.1/README.md",
    "chars": 2730,
    "preview": "# vector-tile-spec\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\",\n\"SHOULD\", \"SHOULD NOT\", \"RECOMME"
  },
  {
    "path": "1.0.1/vector_tile.proto",
    "chars": 4184,
    "preview": "// Protocol Version 1\n\npackage vector_tile;\n\noption optimize_for = LITE_RUNTIME;\n\nmessage Tile {\n        enum GeomType {"
  },
  {
    "path": "2.0/README.md",
    "chars": 22099,
    "preview": "# Vector Tile Specification\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\",\n\"SHOULD\", \"SHOULD NOT\","
  },
  {
    "path": "2.0/vector_tile.proto",
    "chars": 2957,
    "preview": "// Protocol Version 1\n\npackage vector_tile;\n\noption optimize_for = LITE_RUNTIME;\n\nmessage Tile {\n\n        // GeomType is"
  },
  {
    "path": "2.1/README.md",
    "chars": 22462,
    "preview": "# Vector Tile Specification\n\nThe key words \"MUST\", \"MUST NOT\", \"REQUIRED\", \"SHALL\", \"SHALL NOT\",\n\"SHOULD\", \"SHOULD NOT\","
  },
  {
    "path": "2.1/README_zh.md",
    "chars": 12629,
    "preview": "# 矢量瓦片标准\n\n本文档中的“**必须**”、“**必须不**”、“**必备**”、\"**应该**\"、“**不应该**”、“**建议**”、“**可以**”、“**可选**”的含义参照[RFC 2119](https://www.ietf"
  },
  {
    "path": "2.1/vector_tile.proto",
    "chars": 2883,
    "preview": "// Protocol Version 1\n\npackage vector_tile;\n\noption optimize_for = LITE_RUNTIME;\n\nmessage Tile {\n\n        // GeomType is"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 4469,
    "preview": "# Vector Tile Spec Changelog\n\n### 2.1\n\nThe 2.1 update of the specification is a correction to the wording in a few locat"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 3407,
    "preview": "## Open Standard\n\nThe Mapbox Vector Tile specification is an open standard maintained by [Mapbox](https://www.mapbox.com"
  },
  {
    "path": "README.md",
    "chars": 1271,
    "preview": "# Mapbox Vector Tile Specification\n\nA specification for encoding tiled vector data.\n\n## License\n\nThe text of this specif"
  }
]

About this extraction

This page contains the full source code of the jingsam/vector-tile-spec GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 12 files (83.8 KB), approximately 24.7k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!