2 个版本 (1 个稳定版)
新 1.0.0 | 2024年8月15日 |
---|---|
0.1.0 | 2024年5月17日 |
#3 在 #bounding-box
每月下载量 106
180KB
4K SLoC
open-vector-tile
关于
A Modified TypeScript implementation of the Mapbox Vector Tile library. It is backwards compatible but offers a lot of new features and improvements including (but not limited to)
- 🔗 轻量级零依赖构建。
- 🌴 正确的模块树摇。
- 🦺 完整的 TypeScript 支持/安全。
- 🗜 预分片和索引几何图形以快速将数据发送到渲染器。
- 🧊 支持 3D 几何图形。
- ♏ 支持每个几何点上的 M-Values(由线和多边形使用)。
- ♻️ 功能属性和 M-Values 存储为“形状”,这重用只需要对值进行查找的对象。
- 🏛 数据的列编码以使其更加紧凑。更好的 gzip 和 brotli 压缩。
- 🪺 支持属性和 m-values 中的嵌套对象。
- 📦 所有功能都支持像 ID 这样的第一类公民
BBOX
数据。 - 🫥 线和多边形支持
offsets
以了解其走过的距离(对于正确渲染跨瓦片的虚线线非常有用)。
灵感
非常有才华的 Markus Tremmel 提出了将迁移从基于行的方法迁移到基于列的方法的想法,这是通过他的 COVTiles 实现的。我想测试简化他的项目的想法,看看这是否值得付出努力。一旦我看到 brotli 压缩具有可比较的结果,我就决定完成这个项目。
动机
由于同时正在构建另一个规范,您可能认为这是浪费时间或创建不必要的利益冲突。 因此,我写了关于这个主题的思考以及为什么创建此规范。
阅读规范
安装
#bun
bun add open-vector-tile
# pnpm
pnpm add open-vector-tile
# yarn
yarn add open-vector-tile
# npm
npm install open-vector-tile
# cargo
cargo install open-vector-tile
项目结构
示例使用
const fs = from 'fs'
import { VectorTile } from 'open-vector-tile'
// assume you can read (.pbf | .mvt | .ovt)
const fixture = fs.readFileSync('./x-y-z.vector.pbf')
// Bun const fixture = new Uint8Array(await Bun.file('./x-y-z.vector.pbf').arrayBuffer())
// load the protobuf parsing it directly
const tile = new VectorTile(fixture)
console.log(tile)
// example layer
const { landuse } = tile.layers
// grab the first feature
console.log(landuse.feature(0))
console.log(landuse.feature(0).loadGeometry())
通用目的 API
瓦片
读取瓦片
const tile = new VectorTile(uint8Array)
读取图层
const layer = tile.layers[layerName]
图层
图层属性
type Extents = 512 | 1024 | 2048 | 4096 | 8192
interface Layer {
// version control helps know what features are available
version: number;
// name of the layer
name: string;
// extent of the vector tile. MUST be one of `512`, `1024`, `2048`, `4096`, `8192`
extent: Extents;
// number of features in the layer
length: number;
}
读取特征
// returns a VectorFeature
const feature = layer.feature(index)
特征
特征类型
// 6 feature types in total plus the old MapboxVectorFeature
export type VectorFeature =
// points may be a collection of points or single point
| OVectorPointsFeature
// lines may be a collection of lines or single line
| OVectorLinesFeature
// polygons may be a collection of polygons or single polygon
| OVectorPolysFeature
// 3D points may be a collection of 3D points or single 3D point
| OVectorPoints3DFeature
// 3D lines may be a collection of 3D lines or single 3D line
| OVectorLines3DFeature
// 3D polygons may be a collection of 3D polygons or single 3D polygon
| OVectorPolys3DFeature
// Can be any form of points, lines, or polygons without any of the new features
// but all the functions. line offsets and bbox will always be defaults.
| MapboxVectorFeature;
特征属性
type Extents = 512 | 1024 | 2048 | 4096 | 8192
interface Feature {
// properties of the feature
properties: any;
// id of the feature
id: number;
// extent of the vector tile. MUST be one of `512`, `1024`, `2048`, `4096`, `8192`
extent: Extents;
}
获取特征的边界框
export type BBox = [left: number, bottom: number, right: number, top: number];
export type BBox3D = [left: number, bottom: number, right: number, top: number, near: number, far: number];
const bbox: BBox | BBox3D = feature.bbox()
将几何形状作为点集合拉取
// supported by all types, points, lines, and polygons
const geometry: Point[] | Point3D[] = feature.loadPoints()
将几何形状作为线集合拉取
// Supported by any line or polygon type
/// points will return an empty array
interface VectorLineWithOffset {
/** the offset of the line to start processing the dash position */
offset: number;
/** the line data */
geometry: VectorLine;
}
interface VectorLine3DWithOffset {
/** the offset of the line to start processing the dash position */
offset: number;
/** the line data */
geometry: VectorLine3D;
}
const geometry: VectorLineWithOffset[] | VectorLine3DWithOffset[] = feature.loadLines()
根据类型相对位置拉取几何形状
const pointFeature: Point[] = (feature as OVectorPointsFeature).loadGeometry()
const lineFeature: VectorLine[] = (feature as OVectorLinesFeature).loadGeometry()
const polyFeature: VectorPoly[] = (feature as OVectorPolysFeature).loadGeometry()
const point3DFeature: Point3D[] = (feature as OVectorPoints3DFeature).loadGeometry()
const line3DFeature: VectorLine3D[] = (feature as OVectorLines3DFeature).loadGeometry()
const poly3DFeature: VectorPoly3D[] = (feature as OVectorPolys3DFeature).loadGeometry()
如果是多边形类型,则拉取带有索引和细分数据的原始几何形状
// works for any polygon or polygon3D type.
// NOTE: If the indices is empty, then the geometry was never pre-earcut and you need to fallback to `loadGeometry` instead.
const geometry: [geometry: number[], indices: number[]] = feature.loadGeometryFlat()
创建和验证您的形状
形状定义了可以存储在矢量瓦片中的数据类型。它们在规范中进行了说明。
如果您想验证形状,请随意使用Ajv库。
import Ajv from 'ajv';
import { ShapeSchema } from 'open-vector-tile'; // Path to the schema
import type { Shape } from 'open-vector-tile';
const ajv = new Ajv();
const validate = ajv.compile(ShapeSchema);
const shape: Shape = {
a: 'i64',
b: ['string'],
c: {
d: 'f64',
e: 'bool',
f: 'null',
g: 'f32',
h: {
i: 'u64',
},
},
};
validate(shape); // true
开发
需求
您需要一个名为tarpaulin
的工具来生成覆盖率报告。使用以下命令安装它:
cargo install cargo-tarpaulin
bacon coverage
工具用于生成覆盖率报告。要使用pycobertura包生成更漂亮的覆盖率报告,请使用以下命令安装它:
pip install pycobertura
运行测试
要运行测试,请使用以下命令:
# TYPESCRIPT
## basic test
bun run test
## live testing
bun run test:dev
# RUST
## basic test
cargo test
# live testing
bacon test
生成覆盖率报告
要生成覆盖率报告,请使用以下命令:
cargo tarpaulin
# bacon
bacon coverage # or type `l` inside the tool
依赖项
~0.9–1.8MB
~39K SLoC