Vector Tile Specification 2.1

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vector Tile Specification 2.1相关的知识,希望对你有一定的参考价值。

参考技术A

原文链接 https://github.com/mapbox/vector-tile-spec/tree/master/2.1/

在此文档中, 关于关键词【必须】、【禁止】、【必要的】、【应当】、【不应】、【推荐的】、【可以】与【可选的】的解释, 见 RFC 2119 中的描述。

此文档为矢量瓦片地理数据指定了一种节省空间的编码格式。 它被设计用于浏览器或服务器端应用程序,用于快速呈现或查找特征数据。

矢量瓦片格式使用 Google Protocol Buffers 编码格式. Protocol Buffers是一种与语言无关、与平台无关的可扩展序列化机制。

矢量瓦片文件的扩展名 应该 为 mvt . 例如 vector.mvt .

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

矢量瓦片表示一个整正方形范围内投影的数据。矢量瓦片 不应 包含关于边界和投影的信息。这个文件格式假定解码器在解码之前就已经知道投影和边界信息。

Web Mercator 是一个投影的参考, the Google tile scheme 是一个常见的范围参考. 它们一起提供了特定地理区域、特定细节级别和路径之间的一对一关系 ,例如 https://example.com/17/65535/43602.mvt .

矢量瓦片可以用任何投影和瓦片范围方案来表示数据。

这个规范描述了矢量瓦片的数据结构。 读者应该了解 矢量瓦片的protobuf的数据文档 及其定义的结构。

矢量瓦片由一组命名的层组成。每一层包含地理特征和它的元数据。层格式的设计使一层所需的数据在内存中是连续的,因此层可以添加到矢量瓦片中而不需要修改现有的数据。

一个实例瓦片 应该 至少包含一层。一层 应该 至少包含一个特征。

必须 包含 version 字段,此字段为图层所依赖矢量瓦片规范版本号的主版本号。例如,一个符合2.1版本规范的图层包含一个整数值为\' 2 \'的 version 字段。 version 字段 应该 是层中的第一个字段。 解码器 应该 首先解析 version ,以确保他们能够解码每一层。 当矢量瓦片用户遇到一个矢量瓦片层的未知版本时,它 可能 会尽最大努力尝试解释该层,或者跳过该层。 无论哪种情况,它都 应该 继续处理矢量瓦片中的后续图层 。

一个图层必须包含一个 name 字段. 一个实例瓦片 禁止 有两个或两个以上名字完全一样的图层.。在添加一个图层到现有的矢量瓦片之前,编码器 必须 检查现有的 name 字段,以防止重复。

层中的每个特征(见下文)都可以有一个或多个键值对作为元数据。 键和值是两个列表 keys 和 values 的索引,这两个列表是跨层特征共享的。

图层中 keys 字段中的每个元素为字符串。 keys 包含图层所用到的特征,每个键都可以通过它在这个集合中的位置来索引,索引从0开始。 keys 不应 包含两个完全一样的值。

图层中 values 字段中的每个元素为以下几种类型. values 表示图层中用到的所有特征的值,每个值都可以通过它在这个集合中的位置的来索引,索引从0开始。 values 不应 包含两个完全一样的值。

为了支持不同的string, boolean, integer, 和浮点型类型, 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)` 则完全在瓦片之外.

feature 必须 包含一个 geometry 字段。

feature 必须 包含一个 type 字段,如果几何类型(Geometry Types)部分所属

feature 必须 包含一个 tags 字段,如果存在Feature-level metadata,他们 应该 存储在 tags 字段。

feature 必须 包含一个 id 字段。 如果feature包含 id 字段, id 的值 应该 在其所在的图层内保证唯一。

矢量瓦片的几何数据定义在一个屏幕坐标系中。瓦片的左上角为坐标系的原点(默认显示)。X轴正方向朝右,Y轴正方向朝下。几何 坐标 必须为整数。

每个几何图形被编码为32位无符号整数序列并存储在feature的 geometry 字段中。每个整数要么是 命令整数 CommandInteger 要么是参数整数 ParameterInteger . 解释器把它们解析为一系列有序操作,来生成模型。

命令中的位置是相对"cursor"的,"cursor"是一个可以重定义的点。 feature执行第一个命令时 cursor 在 坐标系的 (0,0) 位置。其他命令有可能移动cursor,去影响后续命令。

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 三者关系可由以下位操作表示:

command ID用来表示以下命令:

命令用到的参数在 ParameterInteger 后面。 ParameterIntegers 的数量等于命令的参数个数乘以 CommandInteger 的command count。 比如, CommandInteger 有一个 MoveTo 命令,command count 为 3,那么在后面根6个 ParameterIntegers 。

ParameterInteger 采用 zigzag 编码,所以小的正数或者负数都会被编码成小整数。 parameter value转 ParameterInteger 公式为:

Parameter values不支持 大于 pow(2,31) - 1 或者小于 -1 * (pow(2,31) - 1) 的值。

解码 ParameterInteger 的公式:

对所有命令的描述中,初始坐标记作 (cX, cY) ,即 cursor 的坐标。

MoveTo 命令的 command count 为 n , 那么它后边必须跟随 n 对 ParameterInteger 。每对为 (dX, dY) :

LineTo 命令的 command count 为 n , 那么它后边必须跟随 n 对 ParameterInteger 。每对为 (dX, dY) :

任何 (dX, dY) 中 dX 和 dY 禁止 同时为 0 .

ClosePath 命令command count 必须为 1 且不带 ParameterInteger 。此命令创建一个从cursor (cX, cY) 开始到起始点结束的线段,来完成POLYGON 几何图形中当前的线性环的绘制。

此命令不改变 cursor位置。

在feature中 type 字段来描述 geometry 的类型 ,其值为取自枚举 GeomType 。以下几何类型被支持:

不支持几何图形集合。

该规范有意留下一个未知的几何类型作为选项。 这种几何类型对编码器可以选择实现的实验几何类型进行编码。 这种几何类型可以作为实验性的类型被某些编码器所执行。解码器可能会忽略这种几何类型的任何特征。

POINT 类型,表示一个或多个点的几何图形。此类型的命令序列 必须 是一个command count大于0的 MoveTo 的命令。

如果 POINT 类型的 MoveTo 命令的command count 等于 1,那么该几何图形 一定 是一个单点,否则,几何图形必须被解释为多点几何图形,其中每一对 ParameterInteger 为一个单点。

LINESTRING 类型表示 单个线条的 linestring 或多线条组合的 multilinestring 几何图形。此类型的命令序列必须由以下一个或者多个重复的序列组成 :

如果 LINESTRING 的命令序列只包含一个 MoveTo 命令,那么该图形一定被解释为单条线段的几何图形 ;否则,该几何图形一定被解释为多条线段组合的图形,每一个 MoveTo 命令表示新线条的起始点。

POLYGON 类型用来表示 单个多边形或这个组合多边形的几何图形, 每个多边形仅由一个外环组成,而外环又包含零个或多个内环。 此类型的命令序列必须由以下一个或者多个重复的序列组成 :

每一个 ExteriorRing 和 InteriorRing 必须由以下序列组成:

exterior ring 被定义为线性环,通过 计算公式 计算其面积为正数,在瓦片坐标系中(Y 轴正向朝下, X 轴正向朝右) 外环为顺时针顺序。

interior ring 被定义为线性环,通过 计算公式 计算其面积为负数,在瓦片坐标系中(Y 轴正向朝下, X 轴正向朝右) 外环为逆时针顺序。

如果一个 POLYGON 类型的命令序列中只有一个外环那么它一定被解释为一个多边形,否则它 一定 是一个多边形组合的图形,其每一个内环标示着一个新多边形的起点。如果一个多边形有内环,它们 必须 跟在它们所属的多边形的外环之后。

线性环 必须 是没有异常几何点的几何物体,如自交或自切。 在调用线性环的 ClosePath 命令之前,cursor的位置 不应 与线性环的第一个点重复,因为这会创建一个长度为0的线段。 线性环的面积 不应 为零,因为这意味着环上有异常的几何点。

多边形几何形状 不应 有任何内环相交,内环 必须 由外环包围。

表示一个点:

仅需要一条命令:

表示两个点分别位于:

这需要两条命令:

表示由以下点组成的Linestring:

这需要三条命令:

表示两个Linestring:

需要以下命令:

表示由以下点组成的多边形:

需要以下命令:

下边的示例 由两个多边形组成 ,其中一个有一个洞。多边形的顶点如下所示。多边形的顺序在这个例子中是 非常 重要的,因为它表示内环和新多边形之间的区别。

此多边形需要以下命令:

特征属性位于feature的 tag 字段,为成对的整数。每一对中的第一个整数为 layer 中 keys 的索引(从0开始),用来表示它属于此特征, 每一对中的第二个整数为 layer 中 values 的索引(从0开始),用来表示它属于此特征。每个键索引在该特性中 必须 是唯一的,这样该特性中的其他属性对就不会有相同的键索引。 一个特性必须有偶数个 tag 字段。特性 tag 自动中的键和值分别不能大于等于 keys values 集合元素的数量。

例如, 一个 GeoJSON 特征:

可以被构造为这样:

记住,几何形状的精确值会根据贴图的投影和范围而不同。

背水一战 Windows 10 (109) - 通知(Tile): 按计划显示 tile 通知, 轮询服务端以更新 tile 通知

[源码下载]


背水一战 Windows 10 (109) - 通知(Tile): 按计划显示 tile 通知, 轮询服务端以更新 tile 通知



作者:webabcd


介绍
背水一战 Windows 10 之 通知(Tile)

  • 按计划显示 tile 通知
  • 轮询服务端以更新 tile 通知



示例
1、演示如何按计划显示 tile 通知(在指定的时间显示指定的 tile 通知,此特性在 application tile 和 secondary tile 中均支持)
Notification/Tile/Schedule.xaml

<Page
    x:Class="Windows10.Notification.Tile.Schedule"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Notification.Tile"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <TextBlock Name="lblMsg" Margin="5" />

            <!--显示指定 secondary tile 的全部 ScheduledTileNotification 列表-->
            <ListBox Name="listBox" Width="800" Height="400" Margin="5" HorizontalAlignment="Left">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding Id}" VerticalAlignment="Center" />
                            <TextBlock Text="{Binding Tag}" Margin="15 0 0 0" VerticalAlignment="Center" />
                            <HyperlinkButton Name="btnRemoveScheduledTile" Content="删除此 ScheduledTileNotification" Tag="{Binding Id}" Margin="15 0 0 0" Click="btnRemoveScheduledTile_Click" />
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

            <Button Name="btnAddScheduledTile" Content="添加指定的 ScheduledTileNotification 到指定的 secondary tile 的计划列表中" Click="btnAddScheduledTile_Click" Margin="5" />
        
        </StackPanel>
    </Grid>
</Page>

Notification/Tile/Schedule.xaml.cs

/*
 * 演示如何按计划显示 tile 通知(在指定的时间显示指定的 tile 通知,此特性在 application tile 和 secondary tile 中均支持)
 * 
 * ScheduledTileNotification - 按计划显示的 Tile 通知
 *     Content - Tile 的内容,XmlDocument 类型的数据,只读,其需要在构造函数中指定
 *     DeliveryTime - 显示 Tile 通知的时间,只读,其需要在构造函数中指定
 *     ExpirationTime - Tile 通知的过期时间,超过这个时间就会清除这个 Tile
 *     Id - ScheduledTileNotification 的标识
 *     Tag - 在启用 tile 的队列功能时,如果 tile 的 Tag 相同则新的内容会更新旧的内容(Tag 值的前 16 个字符相同则认为是相同的 Tag)
 *         不指定的 Tag 的话则认为 Tag 都是不同的
 *     
 * TileUpdater - 磁贴的 Tile 更新器
 *     AddToSchedule() - 将指定的 ScheduledTileNotification 对象添加到计划列表
 *     RemoveFromSchedule() - 从计划列表中移除指定的 ScheduledTileNotification 对象
 *     GetScheduledTileNotifications() - 获取全部 ScheduledTileNotification 对象列表
 */

using System;
using System.Collections.Generic;
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
using Windows.UI.StartScreen;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace Windows10.Notification.Tile
{
    public sealed partial class Schedule : Page
    {
        private const string TILEID = "tile_schedule";

        public Schedule()
        {
            this.InitializeComponent();
        }

        // 在开始屏幕固定一个 secondary tile 磁贴
        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            Uri square150x150Logo = new Uri("ms-appx:///Assets/Square150x150Logo.png");
            Uri wide310x150Logo = new Uri("ms-appx:///Assets/Wide310x150Logo.png");
            Uri square310x310Logo = new Uri("ms-appx:///Assets/Square310x310Logo.png");
            SecondaryTile secondaryTile = new SecondaryTile(TILEID, "name", "arguments", square150x150Logo, TileSize.Wide310x150);
            secondaryTile.VisualElements.Wide310x150Logo = wide310x150Logo;
            secondaryTile.VisualElements.Square310x310Logo = square310x310Logo;

            try
            {
                bool isPinned = await secondaryTile.RequestCreateAsync();
                lblMsg.Text = isPinned ? "固定成功" : "固定失败";
            }
            catch (Exception ex)
            {
                lblMsg.Text = "固定失败: " + ex.ToString();
            }

            ShowScheduledTiles();
        }

        // 添加指定的 ScheduledTileNotification 到指定的 secondary tile 的计划列表中
        private void btnAddScheduledTile_Click(object sender, RoutedEventArgs e)
        {
            string tileXml = $@"
                <tile>
                    <visual>
                        <binding template=‘TileSmall‘>
                            <text>Small(小){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                        <binding template=TileMedium>
                            <text>Medium(中){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                        <binding template=TileWide>
                            <text>Wide(宽){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                        <binding template=TileLarge>
                            <text>Large(大){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                    </visual>
                </tile>";

            XmlDocument tileDoc = new XmlDocument();
            tileDoc.LoadXml(tileXml);

            // 实例化 ScheduledTileNotification 对象(15 秒后显示此 Tile 通知)
            DateTime dt = DateTime.Now.AddSeconds(15);
            ScheduledTileNotification tileNotification = new ScheduledTileNotification(tileDoc, dt);

            tileNotification.Id = new Random().Next(100000, 1000000).ToString(); ;
            tileNotification.Tag = $"在 {dt.ToString("HH:mm:ss")} 时显示此 tile 通知";

            // 将指定的 ScheduledTileNotification 对象添加进指定的 secondary tile 的计划列表
            TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(TILEID);
            tileUpdater.AddToSchedule(tileNotification);
            tileUpdater.EnableNotificationQueue(true); // 启用 tile 的队列功能(最多可容纳 5 个 tile)

            ShowScheduledTiles();
        }

        // 删除指定 secondary tile 的指定 ScheduledTileNotification 对象
        private void btnRemoveScheduledTile_Click(object sender, RoutedEventArgs e)
        {
            string notificationId = (string)(sender as FrameworkElement).Tag;

            // 获取指定 secondary tile 的全部 ScheduledTileNotification 对象列表
            TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(TILEID);
            IReadOnlyList<ScheduledTileNotification> notifications = tileUpdater.GetScheduledTileNotifications();

            int notificationCount = notifications.Count;
            for (int i = 0; i < notificationCount; i++)
            {
                if (notifications[i].Id == notificationId)
                {
                    // 从计划列表中移除指定的 ScheduledTileNotification 对象
                    tileUpdater.RemoveFromSchedule(notifications[i]);
                    break;
                }
            }

            ShowScheduledTiles();
        }

        // 显示指定 secondary tile 的全部 ScheduledTileNotification 列表
        private void ShowScheduledTiles()
        {
            // 获取指定 secondary tile 的全部 ScheduledTileNotification 对象列表
            TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(TILEID);
            IReadOnlyList<ScheduledTileNotification> notifications = tileUpdater.GetScheduledTileNotifications();

            listBox.ItemsSource = notifications;
        }
    }
}


2、演示如何轮询服务端以更新 tile 通知
Notification/Tile/Periodic.xaml

<Page
    x:Class="Windows10.Notification.Tile.Periodic"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Notification.Tile"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <TextBlock Name="lblMsg" Margin="5" />
            
            <Button Name="btnStartPeriodicUpdate" Content="启动一个“轮询服务端获取数据,然后更新 Tile 通知”的任务" Click="btnStartPeriodicUpdate_Click" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Notification/Tile/Periodic.xaml.cs

/*
 * 演示如何轮询服务端以更新 tile 通知
 *     
 * TileUpdater - 磁贴的 Tile 更新器
 *     StartPeriodicUpdate(Uri tileContent, DateTimeOffset startTime, PeriodicUpdateRecurrence requestedInterval) - 启动一个“轮询服务端获取数据,然后更新 Tile 通知”的任务
 *     StartPeriodicUpdateBatch(IEnumerable<Uri> tileContents, DateTimeOffset startTime, PeriodicUpdateRecurrence requestedInterval) - 启动一个“轮询服务端获取数据,然后更新 Tile 通知”的任务
 *         tileContent - Tile 通知的内容(xml 格式数据)的 uri 地址(通过 StartPeriodicUpdateBatch 方法指定多个则会循环显示)
 *         startTime - 可以指定启动此任务的时间
 *             指定此值时的逻辑为:首先会立刻请求服务端获取数据,然后在到达 startTime 指定的时间点后再次获取数据,最后再每次按 requestedInterval 指定的间隔轮询服务端
 *         requestedInterval - 轮询服务端的周期(PeriodicUpdateRecurrence 枚举)
 *             HalfHour, Hour, SixHours, TwelveHours, Daily
 *     StopPeriodicUpdate() - 停止“轮询服务端获取数据,然后更新 Tile 通知”的任务
 *     
 *     
 * 注:服务端代码请参见 WebApi/Controllers/TileContentController.cs(有指定 X-WNS-Expires 标头和 X-WNS-Tag 标头的示例)
 */

using System;
using Windows.UI.Notifications;
using Windows.UI.StartScreen;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace Windows10.Notification.Tile
{
    public sealed partial class Periodic : Page
    {
        private const string TILEID = "tile_periodic";

        public Periodic()
        {
            this.InitializeComponent();
        }

        // 在开始屏幕固定一个 secondary tile 磁贴
        protected async override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);

            Uri square150x150Logo = new Uri("ms-appx:///Assets/Square150x150Logo.png");
            Uri wide310x150Logo = new Uri("ms-appx:///Assets/Wide310x150Logo.png");
            Uri square310x310Logo = new Uri("ms-appx:///Assets/Square310x310Logo.png");
            SecondaryTile secondaryTile = new SecondaryTile(TILEID, "name", "arguments", square150x150Logo, TileSize.Wide310x150);
            secondaryTile.VisualElements.Wide310x150Logo = wide310x150Logo;
            secondaryTile.VisualElements.Square310x310Logo = square310x310Logo;

            try
            {
                bool isPinned = await secondaryTile.RequestCreateAsync();
                lblMsg.Text = isPinned ? "固定成功" : "固定失败";
            }
            catch (Exception ex)
            {
                lblMsg.Text = "固定失败: " + ex.ToString();
            }
        }

        // 启动一个“轮询服务端获取数据,然后更新 Tile 通知”的任务
        private void btnStartPeriodicUpdate_Click(object sender, RoutedEventArgs e)
        {
            // 启动一个循环更新 Tile 通知的任务,并指定 Tile 通知的数据源和轮询周期
            TileUpdater tileUpdater = TileUpdateManager.CreateTileUpdaterForSecondaryTile(TILEID);
            tileUpdater.EnableNotificationQueue(true); // 启用 tile 的队列功能(最多可容纳 5 个 tile)

            // 马上请求服务端获取数据,然后 45 分钟之后再次获取数据,最后再每半个小时获取一次数据
            tileUpdater.StartPeriodicUpdate(new Uri("http://localhost:44914/api/TileContent", UriKind.Absolute), DateTimeOffset.UtcNow.AddMinutes(45), PeriodicUpdateRecurrence.HalfHour);

            // Tile 通知的数据源示例请参见 WebApi/Controllers/TileContentController.cs
        }
    }
}

/WebApi/Controllers/TileContentController.cs(服务端代码)

/*
 * 用于演示“轮询服务端以更新 tile 通知”的服务端部分
 */

using System;
using System.Net.Http;
using System.Text;
using System.Web.Http;

namespace WebApi.Controllers
{
    public class TileContentController : ApiController
    {
        private Random _random = new Random();

        [HttpGet]
        public HttpResponseMessage Get()
        {
            string tileXml = $@"
                <tile>
                    <visual>
                        <binding template=‘TileSmall‘>
                            <text>Small(小){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                        <binding template=TileMedium>
                            <text>Medium(中){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                        <binding template=TileWide>
                            <text>Wide(宽){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                        <binding template=TileLarge>
                            <text>Large(大){DateTime.Now.ToString("HH:mm:ss")}</text>
                        </binding>
                    </visual>
                </tile>";

            HttpResponseMessage result = new HttpResponseMessage
            {
                Content = new StringContent(tileXml, Encoding.UTF8, "text/html")
            };

            // Tile 通知的过期时间,超过这个时间就会清除这个 Tile(对于“轮询服务端以更新 Tile 通知”来说,如果不指定此值,则默认 3 天后过期)
            // 通过 ToString("R") 可以把日期格式化为“RFC 1123”格式
            result.Headers.Add("X-WNS-Expires", DateTime.UtcNow.AddSeconds(60).ToString("R")); // 60 秒后过期

            // 在启用 tile 的队列功能时,如果 tile 的 Tag 相同则新的内容会更新旧的内容(Tag 值的前 16 个字符相同则认为是相同的 Tag)
            // 不指定的 Tag 的话则认为 Tag 都是不同的
            result.Headers.Add("X-WNS-Tag", _random.Next().ToString());

            return result;
        }
    }
}



OK
[源码下载]

以上是关于Vector Tile Specification 2.1的主要内容,如果未能解决你的问题,请参考以下文章

使用java生成mapbox-gl可读的vector tile

矢量切片

添加ArcGIS数据

OpenLayers工作原理

C ++分段故障向量[关闭]

Source和Layer