.. _vector.mvt:

MVT: Mapbox Vector Tiles
========================

.. shortname:: MVT

.. build_dependencies:: (requires SQLite and GEOS for write support)

The MVT driver can read and write Mapbox Vector
Tile files, as standalone files, uncompressed or gzip-compressed
(typical extensions are .pbf, .mvt, .mvt.gz), or a tileset at a given
zoom level of such files. Write support requires GDAL to be built with
libsqlite3 and GEOS support.

Mapbox Vector Tiles stored within a SQLite container conforming to the
MBTiles format are handled by the :ref:`MBTiles <raster.mbtiles>`
driver.

Tilesets of MVT files can for example be generated by
`tippecanoe <https://github.com/mapbox/tippecanoe>`__ or
`tileserver-gl <https://github.com/klokantech/tileserver-gl>`__. The
output file hierarchy will contain a :ref:`metadata.json <mvt_metadata_json>`
file at its root and {z}/{x}/{y}.pbf files with the tiles, where z is
the zoom level and (x, y) the coordinate of the tile in a given zoom
level. The origin of the tiling system is the top-left tile (XYZ
convention). For example, for zoom levels 0 and 1 :

::

   /metadata.json
   /0/
      0/
        0.pbf
   /1/
      0/
        0.pbf
        1.pbf
      1/
        0.pbf
        1.pbf

The driver will assume by default EPSG:3857 (WebMercator) spatial
reference system and Z/X/Y tiling structure, if opening a filename with
{Z}/{X}/{Y}.pbf or {Z}-{X}-{Y}.pbf name, or a zoom level of a tileset.
Otherwise integer coordinates will be reported.

Note: When opening a zoom level of a tileset, the driver will make no
effort of stitching together geometries for features that overlap several
tiles.

Driver capabilities
-------------------

.. supports_create::

.. supports_georeferencing::

.. supports_virtualio::

Connection strings
------------------

The following connection strings are supported:

-  */path/to/some.pbf*
-  *MVT:http[s]://path/to/some.pbf*
-  */path/to/{Z}*: where {Z} is a zoom level between 0 and 30, tiles are
   in /path/to/{Z}/{X}/{Y}.pbf files, and /path/to/metadata.json or
   /path/to.json should typically exist.
-  *MVT:http[s]://path/to/{Z]*

The MVT: prefix may be added before the filename or directory name to
help forcing identification of datasets in some rare cases where
non-guided identification would fail.

.. _mvt_metadata_json:

metadata.json
-------------

This file is typically generated by tippecanoe and has the following
content:

.. code-block:: json

   {
       "name": "my_layername",
       "description": "my_layername",
       "version": "2",
       "minzoom": "0",
       "maxzoom": "0",
       "center": "2.500000,49.500000,0",
       "bounds": "2.000000,49.000000,3.000000,50.000000",
       "type": "overlay",
       "format": "pbf",
       "json": "{
           \"vector_layers\": [ {
               \"id\": \"my_layername\",
               \"description\": \"\",
               \"minzoom\": 0,
               \"maxzoom\": 0,
               \"fields\": {
                   \"bool_false\": \"Boolean\",
                   \"bool_true\": \"Boolean\",
                   \"float_value\": \"Number\",
                   \"pos_int_value\": \"Number\",
                   \"pos_int64_value\": \"Number\",
                   \"neg_int_value\": \"Number\",
                   \"neg_int64_value\": \"Number\",
                   \"pos_sint_value\": \"Number\",
                   \"pos_sint64_value\": \"Number\",
                   \"neg_sint_value\": \"Number\",
                   \"neg_sint64_value\": \"Number\",
                   \"real_value\": \"Number\",
                   \"string_value\": \"String\",
                   \"uint_value\": \"Number\",
                   \"uint64_value\": \"Number\"
               }
           } ],
           \"tilestats\": {
               \"layerCount\": 1,
               \"layers\": [
                   {
                   \"layer\": \"my_layername\",
                   \"count\": 2,
                   \"geometry\": \"Point\",
                   \"attributeCount\": 0,
                   \"attributes\": []
                   }
               ]
           }
       }}"
   }

The MVT driver only uses the "json" key to retrieve the layer names,
their fields and the geometry type, and the "bounds" key for the layer
extent.

If this file cannot be found, the layer schema is established by
scanning the features of the tile(s).

As an extension, OGR handles in reading and writing custom tiling
schemes by using the *crs*, *tile_origin_upper_left_x*,
*tile_origin_upper_left_y*, *tile_dimension_zoom_0*, *tile_matrix_width_zoom_0*
and *tile_matrix_height_zoom_0* metadata items.
For example, for the Finnish ETRS-TM35FIN (EPSG:3067) tiling scheme:

.. code-block:: json

   {
     "...": "...",
     "crs":"EPSG:3067",
     "tile_origin_upper_left_x":-548576.0,
     "tile_origin_upper_left_y":8388608.0,
     "tile_dimension_zoom_0":2097152.0,
   }

Or for a ``WorldCRS84Quad`` tiling scheme with 2 tiles in the horizontal
direction at zoom level 0:

.. code-block:: json

   {
     "...": "...",
     "crs":"EPSG:4326",
     "tile_origin_upper_left_x":-180.0,
     "tile_origin_upper_left_y":90.0,
     "tile_dimension_zoom_0":180.0,
     "tile_matrix_width_zoom_0":2,
     "tile_matrix_height_zoom_0":1
   }

Opening options
---------------

|about-open-options|
The following open options are available:

-  .. oo:: X
      :choices: <integer>

      X coordinate of the EPSG:3857 tile.

-  .. oo:: Y
      :choices: <integer>

      Y coordinate of the EPSG:3857 tile.

-  .. oo:: Z
      :choices: <integer>

      Z coordinate of the EPSG:3857 tile.

-  .. oo:: METADATA_FILE
      :choices: <filename>

      Filename of a metadata.json-like file.
      If opening a /path/to/{Z}/{X}/{Y}.pbf file, the driver will by
      default try to find /path/to/metadata.json. Setting the value to the
      empty string is a way of avoid the metadata.json file to be used.

-  .. oo:: CLIP
      :choices: YES, NO
      :default: YES

      Whether to clip geometries of vector features to
      tile extent. Generators of vector tiles will typically create
      geometries with a small buffer beyond the tile extent so that
      geometries intersecting several tiles can be unioned back. Defaults
      to YES so that that buffer is removed and geometries are clipped
      exactly to the tile extent.

-  .. oo:: TILE_EXTENSION
      :default: pbf

      For tilesets, extension of tiles.

-  .. oo:: TILE_COUNT_TO_ESTABLISH_FEATURE_DEFN
      :choices: <integer>
      :default: 1000

      For tilesets
      without metadata file, maximum number of tiles to use to establish
      the layer schemas.

Creation issues
---------------

Tiles are generated with WebMercator (EPSG:3857) projection by default
(custom tiling schemes can be defined with the TILING_SCHEME option).
Several layers can be written. It is possible to decide at which zoom
level ranges a given layer is written.

Part of the conversion is multi-threaded by default, using as many
threads as there are cores. The number of threads used can be controlled
with the :config:`GDAL_NUM_THREADS` configuration option.

Dataset creation options
------------------------

|about-dataset-creation-options|
The following dataset creation options are supported:

-  .. co:: NAME

      Tileset name. Defaults to the basename of the
      output file/directory. Used to fill metadata records.

-  .. co:: DESCRIPTION

      A description of the tileset. Used to fill metadata records.

-  .. co:: TYPE
      :choices: overlay, baselayer

      Layer type. Used to fill metadata records.

-  .. co:: FORMAT
      :choices: DIRECTORY, MBTILES

      Format into which tiles are written.
      DIRECTORY means that tiles are written in a hierarchy like
      out_dir/{z}/{x}/{y}.pbf. MBTILES is for a MBTILES container. Defaults
      to DIRECTORY, unless the output filename has a .mbtiles extension

-  .. co:: TILE_EXTENSION
      :default: pbf

      For tilesets as directories of files,
      extension of tiles.

-  .. co:: MINZOOM
      :choices: <integer>
      :default: 0

      Minimum zoom level at which tiles are generated.

-  .. co:: MAXZOOM
      :choices: <integer>
      :default: 5

       Maximum zoom level at which tiles are
       generated. Maximum supported value is 22.

-  .. co:: CONF
      :choices: <json>, <filename>

      Layer configuration as a JSON serialized string.
      Or, starting with GDAL 3.0.1, filename containing the configuration as JSON .

-  .. co:: SIMPLIFICATION
      :choices: float

      Simplification factor for linear or
      polygonal geometries. The unit is the integer unit of tiles after
      quantification of geometry coordinates to tile coordinates. Applies
      to all zoom levels, unless :co:`SIMPLIFICATION_MAX_ZOOM` is also defined.

-  .. co:: SIMPLIFICATION_MAX_ZOOM
      :choices: <float>

      Simplification factor for linear
      or polygonal geometries, that applies only for the maximum zoom
      level.

-  .. co:: EXTENT
      :choices: <positive integer>
      :default: 4096

      Number of units in a tile. The
      greater, the more accurate geometry coordinates (at the expense of
      tile byte size).

-  .. co:: BUFFER
      :choices: <positive integer>

      Number of units for geometry
      buffering. This value corresponds to a buffer around each side of a
      tile into which geometries are fetched and clipped. This is used for
      proper rendering of geometries that spread over tile boundaries by
      some rendering clients. Defaults to 80 if :co:`EXTENT=4096`.

-  .. co:: COMPRESS
      :choices: YES, NO
      :default: YES

      Whether to compress tiles with the
      Deflate/GZip algorithm. Should be left to YES for
      :co:`FORMAT=MBTILES`.

-  .. co:: TEMPORARY_DB
      :choices: <filename>

      Filename with path for the temporary
      database used for tile generation. By default, this will be a file in
      the same directory as the output file/directory.

-  .. co:: MAX_SIZE
      :choices: <integer>
      :default: 500000

      Maximum size of a tile in bytes (after
      compression). If a tile is greater than this
      threshold, features will be written with reduced precision, or
      discarded.

-  .. co:: MAX_FEATURES
      :choices: <integer>
      :default: 200000

      Maximum number of features per tile.

-  .. co:: BOUNDS
      :choices: <min_long\,min_lat\,max_long\,max_lat>

      Override default
      value for bounds metadata item which is computed from the extent of
      features written.

-  .. co:: CENTER
      :choices: <long\,lat\,zoom_level>

      Override default value for center
      metadata item, which is the center of :co:`BOUNDS` at minimum zoom level.

-  .. co:: TILING_SCHEME
      :choices: <crs\,tile_origin_upper_left_x\,tile_origin_upper_left_y\,tile_dimension_zoom_0[\,tile_matrix_width_zoom_0\,tile_matrix_height_zoom_0]>

      Define a custom tiling scheme with a CRS
      (typically given as EPSG:XXXX), the coordinates of the upper-left
      corner of the upper-left tile (0,0) in the CRS, and the dimension of
      the tile at zoom level 0. Only available for :co:`FORMAT=DIRECTORY`. The
      standard WebMercator tiling scheme would be defined by
      "EPSG:3857,-20037508.343,20037508.343,40075016.686". A tiling scheme
      for WGS84 geodetic could be "EPSG:4326,-180,180,360". The tiling
      scheme for Finnish ETRS-TM35FIN (EPSG:3067) is
      "EPSG:3067,-548576,8388608,2097152". When using such as custom tiling
      scheme, the 'crs', 'tile_origin_upper_left_x',
      'tile_origin_upper_left_y' and 'tile_dimension_zoom_0' entries are
      added to the metadata.json, and are honoured by the OGR MVT reader.
      Starting with GDAL 3.10.2, 'tile_matrix_width_zoom_0' (resp.
      'tile_matrix_height_zoom_0') can be specified to indicate the number of
      tiles along the X (resp. Y) axis at zoom level 0.

Layer configuration
-------------------

The above mentioned CONF dataset creation option can be set to a string
whose value is a JSON serialized document such as the below one:

.. code-block:: json

           {
               "boundaries_lod0": {
                   "target_name": "boundaries",
                   "description": "Country boundaries",
                   "minzoom": 0,
                   "maxzoom": 2
               },
               "boundaries_lod1": {
                   "target_name": "boundaries",
                   "minzoom": 3,
                   "maxzoom": 5
               }
           }

*boundaries_lod0* and *boundaries_lod1* are the name of the OGR layers
that are created into the target MVT dataset. They are mapped to the MVT
target layer *boundaries*.

It is also possible to get the same behavior with the below layer
creation options, although that is not convenient in the ogr2ogr use
case.

Layer creation options
----------------------

|about-layer-creation-options|
The following layer creation options are supported:

-  .. lco:: MINZOOM
      :choices: <integer>

      Minimum zoom level at which tiles are
      generated. Defaults to the dataset creation option :co:`MINZOOM` value.

-  .. lco:: MAXZOOM
      :choices: <integer>

      Maximum zoom level at which tiles are
      generated. Defaults to the dataset creation option :co:`MAXZOOM` value.
      Maximum supported value is 22.

-  .. lco:: NAME

      Target layer name. Defaults to the layer name, but
      can be overridden so that several OGR layers map to a single target
      MVT layer. The typical use case is to have different OGR layers for
      mutually exclusive zoom level ranges.

-  .. lco:: DESCRIPTION

      A description of the layer.

Examples
--------

::

   ogrinfo MVT:https://free.tilehosting.com/data/v3/1 -oo tile_extension="pbf.pict?key=${YOUR_KEY}" --debug on -oo metadata_file="https://free.tilehosting.com/data/v3.json?key=${YOUR_KEY}"

::

   ogr2ogr -f MVT mytileset source.gpkg -dsco MAXZOOM=10

See Also:

-  `Mapbox Vector Tile
   Specification <https://github.com/mapbox/vector-tile-spec>`__
-  :ref:`MBTiles <raster.mbtiles>` driver
-  `tippecanoe <https://github.com/felt/tippecanoe>`__: Builds vector
   tilesets from large (or small) collections of GeoJSON, Geobuf, or CSV
   features
-  `Links to tools dealing with Mapbox Vector
   Tiles <https://github.com/mapbox/awesome-vector-tiles>`__
