ガイドAPIリファレンス
ガイド

ベクタータイルスキーマ

このドキュメント(英語版)のキー ワード「MUST (すべき)」、「MUST NOT (すべきでない)」、「REQUIRED (必須)」、「SHALL (するものとする)」、「SHALL NOT (しないものとする)」、「SHOULD (する必要がある)」、「SHOULD NOT (しないようにする)」、「RECOMMENDED (推奨)」、「MAY (場合がある)」、「OPTIONAL (任意)」は、RFC 2119の記述に従って解釈されます。

ファイル形式

ベクター タイル形式では、エンコード形式として Google Protocol Buffers が使用されます。Protocol Buffers は、構造化データをシリアル化するための、言語やプラットフォームに依存しない拡張可能なメカニズムです。

図法と境界

ベクター タイルは図法内の正方形の範囲に基づいてデータを表します。ベクター タイルには、境界と図法に関する情報を含めないでください。このファイル形式は、デコード前にデコーダーでベクター タイルの境界と図法がわかっていることを前提とします。

Web メルカトルは基準となる図法であり、Google タイル スキームはタイル範囲の基準となる規則です。これらを組み合わせることにより、特定の地理的エリア (特定の詳細レベル) とパスの間に、https://example.com/17/65535/43602.mvt のような 1 対 1 の関係が提供されます。

ベクター タイルは、あらゆる図法およびタイル範囲スキームでデータを表すために使用できます。

内部構造

このドキュメントではベクター タイル内のデータの構造について説明します。このドキュメントを参照する前に、Vector Tile Protobuf スキーマと、そこで定義されている構造を確認してください。

レイヤー

ベクター タイルは、一連の名前付きレイヤーで構成されます。レイヤーには、ジオメトリー フィーチャーとそのメタデータが含まれます。レイヤー形式はレイヤーに必要なデータがメモリ内で連続するように設計されており、既存のデータを変更することなくレイヤーをベクター タイルに追加できるようになっています。

ベクター タイルには 1 つ以上のレイヤーを含めてください。レイヤーには 1 つ以上のフィーチャーを含めてください。

レイヤーには、レイヤーが準拠するベクター タイルの仕様のメジャー バージョン番号を持つ version フィールドを含める必要があります。たとえば、バージョン 2.1 の仕様に準拠するレイヤーには、2 の整数値を持つ version フィールドを含めます。version フィールドはレイヤー内の最初のフィールドにしてください。デコーダーは最初に version を解析して、各層をデコードできることを確認します。ベクター タイル コンシューマが不明なバージョンのベクター タイル レイヤーに遭遇すると、そのレイヤーを解釈するために最善の努力が行われる場合もあれば、レイヤーがスキップされる場合もあります。いずれの場合も、ベクター タイル内の後続のレイヤーの処理を継続する必要があります。

レイヤーには name フィールドを含めなければなりません。ベクター タイルには、name 値がバイト単位で同一のレイヤーを 2 つ以上含めることはできません。重複を防ぐために、レイヤーを既存のベクター タイルに追加する前に、エンコーダで既存の name フィールドを確認する必要があります。

レイヤー内の各フィーチャーには、メタデータとしてキーと値のペアが 1 つ以上含まれる場合があります。キーと値は keys および values の 2 つのリストに分けられたインデックスであり、レイヤーのフィーチャー間で共有されます。

レイヤーの keys フィールドの各要素は文字列です。keys にはレイヤーで使用されるフィーチャーのすべてのキーが含まれます。各キーはこの一連の keys の位置インデックスを使用して参照される場合があります。最初のキーのインデックスは 0 になります。一連の keys には、バイト単位で同一の値を 2 つ以上含めないようにしてください。

レイヤーの values フィールドの各要素は、いくつかのタイプの値をエンコードします (以下を参照)。values はレイヤーで使用されるフィーチャーのすべての値を表します。各値はこの一連の values の位置インデックスを使用して参照される場合があります。最初の値のインデックスは 0 になります。一連の values には、バイト単位で同一の、タイプが同じ値を 2 つ以上含めないようにしてください。

文字列、ブール値、整数、浮動小数点といったさまざまな型の値をサポートするために、value フィールドの Protobuf エンコーディングは、一連の optional フィールドで構成されます。値にはこれらの任意のフィールドのいずれかのみを含める必要があります。

レイヤーにはタイルの幅と高さを整数の座標で表す 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) のポイントはタイルの範囲外です。

フィーチャー

フィーチャーにはgeometryフィールドを含める必要があります。

フィーチャーには、「ジオメトリータイプ」セクションで説明するtypeフィールドを含める必要があります。

フィーチャーには tags フィールドが含まれる場合があります。フィーチャー レベルのメタデータがある場合は、tags フィールドに格納してください。

フィーチャーには id フィールドが含まれる場合があります。フィーチャーに id フィールドがある場合、id の値は親レイヤーのフィーチャー間で一意となるようにします。

ジオメトリーのエンコーディング

ベクター タイルのジオメトリー データは、画面の座標系で定義されます。タイルの左上隅 (デフォルトで表示) が座標系の原点です。X 軸は右側が正、Y 軸は下側が正です。ジオメトリー内の座標は整数である必要があります。

ジオメトリーは、フィーチャーのgeometryフィールドで、32 ビットの符号なし整数のシーケンスとしてエンコードされます。それぞれの整数は CommandInteger または ParameterInteger のいずれかになります。デコーダーは順序付けられた一連の操作としてこれらの数を解釈し、ジオメトリーを生成します。

コマンドは、再定義可能なポイントである、「カーソル」を基準にした位置を参照します。フィーチャーの最初のコマンドの場合、カーソルは座標系の (0,0) にあります。コマンドによっては、カーソルを移動して後続のコマンドに影響を与えるものもあります。

コマンドの整数

CommandInteger は実行されるコマンドをコマンド ID として示し、そのコマンドが実行される回数をコマンド数で示します。

コマンド ID は CommandInteger の最下位 3 ビットで符号なし整数として符号化され、0 以上 7 以下の範囲の値になります。コマンド数は CommandInteger の残りの 29 ビットで符号なし整数としてエンコードされ、0 以上 pow(2, 29) - 1 以下の範囲の値になります。

コマンド ID、コマンド数、CommandInteger は、次のビット単位の演算によって関連付けられます。

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

コマンドIDは、次のいずれかのコマンドを指定します。

コマンドIdパラメーターパラメーター数
MoveTo1dXdY2
LineTo2dXdY2
ClosePath7パラメーターなし0
コマンドの整数の例
コマンドIDCommandIntegerバイナリ表現 [Count][Id]
MoveTo119[00000000 00000000 0000000 00001][001]
MoveTo1120961[00000000 00000000 0000011 11000][001]
LineTo2110[00000000 00000000 0000000 00001][010]
LineTo2326[00000000 00000000 0000000 00011][010]
ClosePath7115[00000000 00000000 0000000 00001][111]

パラメーターの整数

パラメーターを必要とするコマンドの後には、そのコマンドで必要とされる各パラメーターの ParameterInteger が続きます。CommandInteger の後に続く ParameterIntegers の数は、コマンドのパラメーター数に CommandInteger のコマンド数をかけた値なります。たとえば、コマンド数が 3 の MoveTo コマンドを伴う CommandInteger の後には、6 個の ParameterIntegers が続きます。

小さい負の値と正の値が両方とも小さい整数としてエンコードされるように、ParameterIntegerジグザグにエンコードされます。パラメーター値を ParameterInteger にエンコードするには、次の式を使用します。

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

pow(2,31) - 1 より大きいパラメーター値または -1 * (pow(2,31) - 1) より小さいパラメーター値はサポートされていません。

次の数式は、ParameterIntegerを値にデコードするために使用されます。

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

コマンドのタイプ

コマンドのすべての説明で、カーソルの初期位置は座標 (cX, cY) にあると説明されます。この場合 cX は X 軸上のカーソルの位置、cY は Y 軸上の cursor の位置になります。

MoveTo コマンド

コマンド数 nMoveTo コマンドの直後には、n ペアの ParameterInteger を続ける必要があります。各ペア (dX, dY) は、次を行います。

  1. 座標(pX, pY)を定義します。ここでは、pX = cX + dXpY = cY + dY となります。
    • POINTジオメトリーでは、この座標によって新しい点が定義されます。
    • LINESTRINGジオメトリーでは、この座標によって新しい直線の開始頂点が定義されます。
    • POLYGONジオメトリーでは、この座標によって新しい線形リングの開始頂点が定義されます。
  2. カーソルを(pX, pY)に移動します。
LineTo コマンド

コマンド数 nLineTo コマンドの直後には、n ペアの ParameterInteger を続ける必要があります。各ペア (dX, dY) は、次を行います。

  1. カーソル (cX, cY) で始まり、座標 (pX, pY) で終わるセグメントを定義します。ここでは、pX = cX + dXpY = cY + dY となります。
    • LINESTRING ジオメトリーでは、このセグメントによって現在のラインが延長されます。
    • POLYGONジオメトリーでは、このセグメントによって現在の線形リングが延長されます。
  2. カーソルを(pX, pY)に移動します。

(dX, dY)の任意のペアについて、dXdYを両方とも0にすることはできません。

ClosePath コマンド

ClosePath コマンドのコマンド数は 1 であり、パラメーターを持つことはできません。このコマンドは、カーソル (cX, cY) の位置から現在の線形リングの開始頂点で終わる線分を介して、POLYGON ジオメトリーの現在の線形リングを閉じます。

このコマンドによってカーソルの位置が変更されることはありません。

ジオメトリー タイプ

各フィーチャーのフィールド geometry は、type フィールドによって記述されます。このフィールドは列挙型 GeomType の値にする必要があります。次のジオメトリー タイプがサポートされています。

  • UNKNOWN
  • POINT
  • LINESTRING
  • POLYGON

ジオメトリーコレクションはサポートされていません。

不明なジオメトリータイプ

仕様では意図的に不明なジオメトリー タイプがオプションとして残されています。このジオメトリー タイプは、エンコーダーで実装を選択できる実験的なジオメトリー タイプをエンコードします。デコーダーによっては、このジオメトリー タイプのフィーチャーがすべて無視される場合があります。

ポイント ジオメトリー タイプ

POINT ジオメトリー タイプは、ポイントまたはマルチポイント ジオメトリーをエンコードします。ポイント ジオメトリーのジオメトリー コマンド シーケンスは、0 より大きいコマンド数を持つ単一の MoveTo コマンドで構成されている必要があります。

POINT ジオメトリーに対するコマンド MoveTo のコマンド数が 1 の場合、そのジオメトリーは単一のポイントとして解釈されなければなりません。1 以外の場合は、ジオメトリーはマルチポイント ジオメトリーとして解釈され、ParameterInteger の各ペアが単一のポイントをエンコードします。

LineString ジオメトリー タイプ

LINESTRING ジオメトリー タイプは、LineString ジオメトリーまたは MultilineString ジオメトリーをエンコードします。LineString ジオメトリーのジオメトリー コマンド シーケンスは、次のシーケンスの 1 つ以上の繰り返しで構成される必要があります。

  1. コマンド数が1のMoveToコマンド
  2. コマンド数が 0 より大きい LineTo コマンド

LINESTRING ジオメトリー タイプのコマンド シーケンスに単一の MoveTo コマンドのみが含まれている場合は、ジオメトリーを単一の LineString として解釈する必要があります。複数含まれている場合は、ジオメトリーを MultilineString ジオメトリーとして解釈する必要があります。それぞれの MoveTo は、新しい LineString の開始を示します。

ポリゴン ジオメトリー タイプ

POLYGON ジオメトリー タイプは、ポリゴンまたはマルチポリゴンのジオメトリーをエンコードします。各ポリゴンは、ゼロ個以上の内部リングを含む 1 つの外部リングのみで構成されます。ポリゴンのジオメトリー コマンド シーケンスは、次のシーケンスの 1 つ以上の繰り返しで構成されます。

  1. 1 つの ExteriorRing
  2. ゼロ個以上のInteriorRing

ExteriorRingおよびInteriorRingは、次のシーケンスで構成されている必要があります。

  1. コマンド数が1のMoveToコマンド
  2. コマンド数が1より大きいLineToコマンド
  3. ClosePath コマンド

外部リングは、タイル座標のポリゴンの頂点に座標法を適用して計算された、正の領域を持つ線形リングとして定義されます。タイル座標系では (Y 軸は下が正、X 軸は右が正)、外部リングの屈曲の順序が時計回りになります。

内部リングは、タイル座標のポリゴンの頂点に座標法を適用して計算された、負の領域を持つ線形リングとして定義されます。タイル座標系では (Y 軸は下が正、X 軸は右が正)、内側のリングの屈曲の順序が反時計回りになります。

POLYGON ジオメトリー タイプのコマンド シーケンスに単一の外部リングのみが含まれている場合は、ジオメトリーを単一のポリゴンとして解釈する必要があります。複数含まれている場合は、ジオメトリーをマルチポリゴン ジオメトリーとして解釈する必要があります。それぞれの外部リングは、新しいポリゴンの開始を示します。ポリゴンに内部リングがある場合は、その内部リングが属するポリゴンの外部リングの直後にエンコードする必要があります。

線形リングは、自己交差や自己接線などの異常なジオメトリー ポイントを持たないジオメトリー オブジェクトである必要があります。線形リングの ClosePath コマンドを呼び出す前のカーソルの位置は、長さゼロの線分が作成されるため、線形リングの最初の点と同じ位置を繰り返してはなりません。異常なジオメトリー ポイントを持つリングを意味することになるため、線形リングでは、座標法で算出される領域が 0 にならないようにしてください。

ポリゴン ジオメトリーには、交差する内部リングがないようにし、また、内部リングは外部リングで囲む必要があります。

ジオメトリー エンコーディングの例

ポイントの例

次の場所にあるポイントのエンコード例:

  • (25,17)

これには次の単一のコマンドが必要です。

  • 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), command count 1
マルチポイントの例

次の場所にある2つのポイントのエンコード例:

  • (5,7)
  • (3,2)

これには次の2つのコマンドが必要です。

  • 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(+5, +7) == create point (5,7)
               `> [00010 001] = command id 1 (MoveTo), command count 2
LineString の例

ポイントを持つ1つのラインのエンコード例:

  • (2,2)
  • (2,10)
  • (10,10)

これには次の3つのコマンドが必要です。

  • 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), command count 2
              | === relative MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), command count 1
複数の LineString の例

ポイントを持つ2つのラインのエンコード例:

  • ライン 1:
    • (2,2)
    • (2,10)
    • (10,10)
  • ライン 2:
    • (1,1)
    • (3,5) これには、次のコマンドが必要です。
  • 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), command count 1
              |      |           | ===== relative MoveTo(-9, -9) == Start new line at (1,1)
              |      |           `> [00001 001] = command id 1 (MoveTo), command count 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), command count 2
              | === relative MoveTo(+2, +2)
              `> [00001 001] = command id 1 (MoveTo), command count 1
ポリゴンの例

ポイントを持つポリゴンフィーチャーのエンコード例:

  • (3,6)
  • (8,12)
  • (20,34)
  • (3,6) 最終ポイントとしてのパスの終了

次のコマンドを使用してエンコードされます。

  • 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), command count 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), command count 2
              | ==== relative MoveTo(+3, +6)
              `> [00001 001] = command id 1 (MoveTo), command count 1
マルチポリゴンの例

2 つのポリゴンのより複雑なエンコーディングの例。一方には穴があります。ポリゴンのポイントの位置を以下に示します。この例では、内部リングと新しいポリゴンの違いを示すため、ポリゴンの屈曲の順序が非常に重要です。

  • ポリゴン 1:
    • 外部リング:
      • (0,0)
      • (10,0)
      • (10,10)
      • (0,10)
      • (0,0) 最終ポイントとしてのパスの終了
  • ポリゴン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 // ポリゴン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 // 領域が負であるため、これは内部リングです!
Encoded as: [ 9 0 0 26 20 0 0 20 19 0 15 9 22 2 26 18 0 0 18 17 0 15 9 4 13 26 0 8 8 0 0 7 15 ]
              |      |                |  |       |                |  |       |              `> [00001 111] (ClosePath)
              |      |                |  |       |                |  |       `> [00011 010] = (LineTo), command count 3
              |      |                |  |       |                |  `> [00001 001] = command id 1 (MoveTo), command count 1
              |      |                |  |       |                `> [00001 111] (ClosePath)
              |      |                |  |       `> [00011 010] = (LineTo), command count 3
              |      |                | `> [00001 001] = command id 1 (MoveTo), command count 1
              |      |                `> [00001 111] (ClosePath)
              |      `> [00011 010] = (LineTo), command count 3
              `> [00001 001] = command id 1 (MoveTo), command count 1

4.4.フィーチャーの属性

フィーチャーの属性は、整数のペアとしてフィーチャーの tag フィールドにエンコードされます。各ペアの最初の整数は、そのフィーチャーが属する layerkeys セットのゼロから始まるインデックスを表します。各ペアの 2 番目の整数は、フィーチャーが属する layervalues セットの値のゼロから始まるインデックスを表します。そのフィーチャー内の他の属性ペアが同じキー インデックスを持たないようにするために、すべてのキー インデックスはそのフィーチャー内で一意である必要があります。フィーチャーには偶数の tag フィールドが必要です。フィーチャーの tag フィールドには、それぞれレイヤーの keys セットまたは values セットの要素の数以上のキー インデックスまたは値インデックスを含めてはなりません。

たとえば、次のようなGeoJSONフィーチャーがあります。

{
    "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
            }
        }
    ]
}

次のように構成できます。

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
}

ジオメトリーの正確な値はタイルの図法と範囲によって異なります。