@osmix/vt 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @osmix/vt
2
2
 
3
+ ## 0.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [33d9c12]
8
+ - @osmix/shared@0.0.2
9
+ - @osmix/json@0.0.2
10
+
3
11
  ## 0.0.1
4
12
 
5
13
  ### Patch Changes
@@ -0,0 +1,21 @@
1
+ import type { Osmix } from "@osmix/core";
2
+ import type { GeoBbox2D, LonLat, Tile, XY } from "@osmix/shared/types";
3
+ import type { VtSimpleFeature } from "./types";
4
+ export declare function projectToTile(tile: Tile, extent?: number): (ll: LonLat) => XY;
5
+ export declare class OsmixVtEncoder {
6
+ readonly nodeLayerName: string;
7
+ readonly wayLayerName: string;
8
+ private readonly osmix;
9
+ private readonly extent;
10
+ private readonly extentBbox;
11
+ constructor(osmix: Osmix, extent?: number, buffer?: number);
12
+ getTile(tile: Tile): ArrayBuffer;
13
+ getTileForBbox(bbox: GeoBbox2D, proj: (ll: LonLat) => XY): ArrayBuffer;
14
+ nodeFeatures(bbox: GeoBbox2D, proj: (ll: LonLat) => XY): Generator<VtSimpleFeature>;
15
+ wayFeatures(bbox: GeoBbox2D, proj: (ll: LonLat) => XY): Generator<VtSimpleFeature>;
16
+ clipProjectedPolyline(points: XY[]): XY[][];
17
+ clipProjectedPolygon(points: XY[]): XY[];
18
+ processClippedPolygonRing(rawRing: XY[]): XY[];
19
+ clampAndRoundPoint(xy: XY): XY;
20
+ }
21
+ //# sourceMappingURL=encode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../src/encode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAIxC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAA;AACtE,OAAO,KAAK,EACX,eAAe,EAGf,MAAM,SAAS,CAAA;AA2BhB,wBAAgB,aAAa,CAC5B,IAAI,EAAE,IAAI,EACV,MAAM,SAAiB,GACrB,CAAC,EAAE,EAAE,MAAM,KAAK,EAAE,CAGpB;AAED,qBAAa,cAAc;IAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAQ;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;gBAEjD,KAAK,EAAE,KAAK,EAAE,MAAM,SAAiB,EAAE,MAAM,SAAiB;IAa1E,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW;IAMhC,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,EAAE,GAAG,WAAW;IAkBrE,YAAY,CACZ,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,EAAE,GACtB,SAAS,CAAC,eAAe,CAAC;IAkB5B,WAAW,CACX,IAAI,EAAE,SAAS,EACf,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,EAAE,GACtB,SAAS,CAAC,eAAe,CAAC;IAmD7B,qBAAqB,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;IAI3C,oBAAoB,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE;IAIxC,yBAAyB,CAAC,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE;IAc9C,kBAAkB,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE;CAS9B"}
package/dist/encode.js ADDED
@@ -0,0 +1,201 @@
1
+ import { wayIsArea } from "@osmix/json";
2
+ import { clipPolygon, clipPolyline } from "@osmix/shared/lineclip";
3
+ import SphericalMercatorTile from "@osmix/shared/spherical-mercator";
4
+ import writeVtPbf from "./write-vt-pbf";
5
+ const DEFAULT_EXTENT = 4096;
6
+ const DEFAULT_BUFFER = 64;
7
+ const SF_TYPE = {
8
+ POINT: 1,
9
+ LINE: 2,
10
+ POLYGON: 3,
11
+ };
12
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
13
+ function dedupePoints(points) {
14
+ if (points.length < 2)
15
+ return points;
16
+ const result = [];
17
+ let lastPoint = [Number.NaN, Number.NaN];
18
+ for (const point of points) {
19
+ if (point[0] === lastPoint[0] && point[1] === lastPoint[1])
20
+ continue;
21
+ result.push(point);
22
+ lastPoint = point;
23
+ }
24
+ return result;
25
+ }
26
+ export function projectToTile(tile, extent = DEFAULT_EXTENT) {
27
+ const sm = new SphericalMercatorTile({ size: extent, tile });
28
+ return (lonLat) => sm.llToTilePx(lonLat);
29
+ }
30
+ export class OsmixVtEncoder {
31
+ nodeLayerName;
32
+ wayLayerName;
33
+ osmix;
34
+ extent;
35
+ extentBbox;
36
+ constructor(osmix, extent = DEFAULT_EXTENT, buffer = DEFAULT_BUFFER) {
37
+ this.osmix = osmix;
38
+ const min = -buffer;
39
+ const max = extent + buffer;
40
+ this.extent = extent;
41
+ this.extentBbox = [min, min, max, max];
42
+ const layerName = `@osmix:${osmix.id}`;
43
+ this.nodeLayerName = `${layerName}:nodes`;
44
+ this.wayLayerName = `${layerName}:ways`;
45
+ }
46
+ getTile(tile) {
47
+ const sm = new SphericalMercatorTile({ size: this.extent, tile });
48
+ const bbox = sm.bbox(tile[0], tile[1], tile[2]);
49
+ return this.getTileForBbox(bbox, (ll) => sm.llToTilePx(ll));
50
+ }
51
+ getTileForBbox(bbox, proj) {
52
+ const layer = writeVtPbf([
53
+ {
54
+ name: this.wayLayerName,
55
+ version: 2,
56
+ extent: this.extent,
57
+ features: this.wayFeatures(bbox, proj),
58
+ },
59
+ {
60
+ name: this.nodeLayerName,
61
+ version: 2,
62
+ extent: this.extent,
63
+ features: this.nodeFeatures(bbox, proj),
64
+ },
65
+ ]);
66
+ return layer;
67
+ }
68
+ *nodeFeatures(bbox, proj) {
69
+ const nodeIndexes = this.osmix.nodes.withinBbox(bbox);
70
+ for (let i = 0; i < nodeIndexes.length; i++) {
71
+ const nodeIndex = nodeIndexes[i];
72
+ if (nodeIndex === undefined)
73
+ continue;
74
+ const tags = this.osmix.nodes.tags.getTags(nodeIndex);
75
+ if (!tags || Object.keys(tags).length === 0)
76
+ continue;
77
+ const id = this.osmix.nodes.ids.at(nodeIndex);
78
+ const ll = this.osmix.nodes.getNodeLonLat({ index: nodeIndex });
79
+ yield {
80
+ id,
81
+ type: SF_TYPE.POINT,
82
+ properties: { type: "node", ...tags },
83
+ geometry: [[proj(ll)]],
84
+ };
85
+ }
86
+ }
87
+ *wayFeatures(bbox, proj) {
88
+ const wayIndexes = this.osmix.ways.intersects(bbox);
89
+ for (let i = 0; i < wayIndexes.length; i++) {
90
+ const wayIndex = wayIndexes[i];
91
+ if (wayIndex === undefined)
92
+ continue;
93
+ const id = this.osmix.ways.ids.at(wayIndex);
94
+ const tags = this.osmix.ways.tags.getTags(wayIndex);
95
+ const count = this.osmix.ways.refCount.at(wayIndex);
96
+ const start = this.osmix.ways.refStart.at(wayIndex);
97
+ const points = new Array(count);
98
+ for (let i = 0; i < count; i++) {
99
+ const ref = this.osmix.ways.refs.at(start + i);
100
+ const ll = this.osmix.nodes.getNodeLonLat({ id: ref });
101
+ points[i] = proj(ll);
102
+ }
103
+ const isArea = wayIsArea({ id, refs: new Array(count).fill(0), tags });
104
+ const geometry = [];
105
+ if (isArea) {
106
+ // 1. clip polygon in tile coords
107
+ const clippedPoly = this.clipProjectedPolygon(points);
108
+ // clipProjectedPolygon currently returns XY[], not XY[][]
109
+ // i.e. assumes single ring. We'll treat it as one ring.
110
+ // 2. round/clamp, dedupe, close, orient
111
+ const processedRing = this.processClippedPolygonRing(clippedPoly);
112
+ // TODO handle MultiPolygons with holes
113
+ if (processedRing.length > 0) {
114
+ geometry.push(processedRing);
115
+ }
116
+ }
117
+ else {
118
+ const clippedSegmentsRaw = this.clipProjectedPolyline(points);
119
+ for (const segment of clippedSegmentsRaw) {
120
+ const rounded = segment.map((xy) => this.clampAndRoundPoint(xy));
121
+ const deduped = dedupePoints(rounded);
122
+ if (deduped.length >= 2) {
123
+ geometry.push(deduped);
124
+ }
125
+ }
126
+ }
127
+ if (geometry.length === 0)
128
+ continue;
129
+ yield {
130
+ id,
131
+ type: isArea ? SF_TYPE.POLYGON : SF_TYPE.LINE,
132
+ properties: { type: "way", ...tags },
133
+ geometry,
134
+ };
135
+ }
136
+ }
137
+ clipProjectedPolyline(points) {
138
+ return clipPolyline(points, this.extentBbox);
139
+ }
140
+ clipProjectedPolygon(points) {
141
+ return clipPolygon(points, this.extentBbox);
142
+ }
143
+ processClippedPolygonRing(rawRing) {
144
+ // 1. round & clamp EVERY point
145
+ const snapped = rawRing.map((xy) => this.clampAndRoundPoint(xy));
146
+ // 2. clean (dedupe + close + min length)
147
+ const cleaned = cleanRing(snapped);
148
+ if (cleaned.length === 0)
149
+ return [];
150
+ // 3. enforce clockwise for outer ring
151
+ const oriented = ensureClockwise(cleaned);
152
+ return oriented;
153
+ }
154
+ clampAndRoundPoint(xy) {
155
+ const clampedX = Math.round(clamp(xy[0], this.extentBbox[0], this.extentBbox[2]));
156
+ const clampedY = Math.round(clamp(xy[1], this.extentBbox[1], this.extentBbox[3]));
157
+ return [clampedX, clampedY];
158
+ }
159
+ }
160
+ function closeRing(ring) {
161
+ const first = ring[0];
162
+ const last = ring[ring.length - 1];
163
+ if (first === undefined || last === undefined)
164
+ return ring;
165
+ if (first[0] !== last[0] || first[1] !== last[1]) {
166
+ return [...ring, first];
167
+ }
168
+ return ring;
169
+ }
170
+ // Signed area via shoelace formula.
171
+ // Positive area => CCW, Negative => CW.
172
+ function ringArea(ring) {
173
+ let sum = 0;
174
+ for (let i = 0; i < ring.length - 1; i++) {
175
+ const [x1, y1] = ring[i];
176
+ const [x2, y2] = ring[i + 1];
177
+ sum += x1 * y2 - x2 * y1;
178
+ }
179
+ return sum / 2;
180
+ }
181
+ function ensureClockwise(ring) {
182
+ return ringArea(ring) < 0 ? ring : [...ring].reverse();
183
+ }
184
+ /**
185
+ * TODO handle MultiPolygons with holes
186
+ *
187
+ function _ensureCounterClockwise(ring: XY[]): XY[] {
188
+ return ringArea(ring) > 0 ? ring : [...ring].reverse()
189
+ }
190
+ */
191
+ // Remove consecutive duplicates *after* rounding
192
+ function cleanRing(ring) {
193
+ const deduped = dedupePoints(ring);
194
+ // After dedupe, we still must ensure closure, and a polygon
195
+ // ring needs at least 4 coords (A,B,C,A).
196
+ const closed = closeRing(deduped);
197
+ if (closed.length < 4)
198
+ return [];
199
+ return closed;
200
+ }
201
+ //# sourceMappingURL=encode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.js","sourceRoot":"","sources":["../src/encode.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=encode.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.test.d.ts","sourceRoot":"","sources":["../src/encode.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,87 @@
1
+ import { VectorTile } from "@mapbox/vector-tile";
2
+ import { Osmix } from "@osmix/core";
3
+ import SphericalMercatorTile from "@osmix/shared/spherical-mercator";
4
+ import Protobuf from "pbf";
5
+ import { assert, describe, expect, it } from "vitest";
6
+ import { OsmixVtEncoder } from "./encode";
7
+ const osm = new Osmix();
8
+ osm.nodes.addNode({
9
+ id: 1,
10
+ lat: 40,
11
+ lon: -74,
12
+ tags: {
13
+ name: "Test Node",
14
+ },
15
+ });
16
+ // Add nodes for way
17
+ osm.nodes.addNode({
18
+ id: 2,
19
+ lat: 40.72,
20
+ lon: -74.01,
21
+ });
22
+ osm.nodes.addNode({
23
+ id: 3,
24
+ lat: 40.715,
25
+ lon: -74.005,
26
+ });
27
+ osm.nodes.addNode({
28
+ id: 4,
29
+ lat: 40.7122,
30
+ lon: -74.001,
31
+ });
32
+ osm.ways.addWay({
33
+ id: 5,
34
+ refs: [1, 2],
35
+ });
36
+ osm.buildIndexes();
37
+ osm.buildSpatialIndexes();
38
+ const WAY_LAYER_ID = `@osmix:${osm.id}:ways`;
39
+ const NODE_LAYER_ID = `@osmix:${osm.id}:nodes`;
40
+ function decodeTile(data) {
41
+ const tile = new VectorTile(new Protobuf(data));
42
+ return tile.layers;
43
+ }
44
+ const extent = 4096;
45
+ const merc = new SphericalMercatorTile({ size: extent });
46
+ function pointToTile(lon, lat, z) {
47
+ const [px, py] = merc.px([lon, lat], z);
48
+ const x = Math.floor(px / extent);
49
+ const y = Math.floor(py / extent);
50
+ return [x, y, z];
51
+ }
52
+ function bboxToTile(bbox, z = 8) {
53
+ const [minX, minY, maxX, maxY] = bbox;
54
+ const centerLon = (minX + maxX) / 2;
55
+ const centerLat = (minY + maxY) / 2;
56
+ return pointToTile(centerLon, centerLat, z);
57
+ }
58
+ describe("OsmixVtEncoder", () => {
59
+ it("encodes nodes and ways with expected metadata", () => {
60
+ const bbox = osm.bbox();
61
+ const tile = bboxToTile(bbox);
62
+ const encoder = new OsmixVtEncoder(osm);
63
+ const result = encoder.getTile(tile);
64
+ expect(result.byteLength).toBeGreaterThan(0);
65
+ const layers = decodeTile(result);
66
+ assert.isDefined(layers[NODE_LAYER_ID]);
67
+ expect(layers[NODE_LAYER_ID].length).toBe(1);
68
+ assert.isDefined(layers[WAY_LAYER_ID]);
69
+ expect(layers[WAY_LAYER_ID].length).toBe(1);
70
+ const features = [
71
+ layers[NODE_LAYER_ID].feature(0),
72
+ layers[WAY_LAYER_ID].feature(0),
73
+ ];
74
+ const node = features.find((feature) => feature.properties["type"] === "node");
75
+ expect(node?.id).toBe(1);
76
+ expect(node?.type).toBe(1);
77
+ const nodeGeom = node?.loadGeometry();
78
+ expect(nodeGeom?.[0]?.[0]?.x).toBeTypeOf("number");
79
+ expect(nodeGeom?.[0]?.[0]?.y).toBeTypeOf("number");
80
+ const way = features.find((feature) => feature.properties["type"] === "way");
81
+ expect(way?.id).toBe(5);
82
+ expect(way?.type).toBe(2);
83
+ const wayGeom = way?.loadGeometry();
84
+ expect(wayGeom?.[0]?.length).toBeGreaterThanOrEqual(2);
85
+ });
86
+ });
87
+ //# sourceMappingURL=encode.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"encode.test.js","sourceRoot":"","sources":["../src/encode.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { OsmixVtEncoder } from "./encode";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { OsmixVtEncoder } from "./encode";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,26 @@
1
+ import type { OsmEntityType, OsmTags } from "@osmix/json";
2
+ import type { XY } from "@osmix/shared/types";
3
+ export type VtSimpleFeatureGeometry = XY[][];
4
+ export type VtSimpleFeatureProperties = {
5
+ sourceId?: string;
6
+ type: OsmEntityType;
7
+ tileKey?: string;
8
+ } & OsmTags;
9
+ export type VtSimpleFeatureType = {
10
+ POINT: 1;
11
+ LINE: 2;
12
+ POLYGON: 3;
13
+ };
14
+ export interface VtSimpleFeature {
15
+ id: number;
16
+ type: VtSimpleFeatureType[keyof VtSimpleFeatureType];
17
+ properties: VtSimpleFeatureProperties;
18
+ geometry: VtSimpleFeatureGeometry;
19
+ }
20
+ export type VtPbfLayer = {
21
+ name: string;
22
+ version: number;
23
+ extent: number;
24
+ features: Generator<VtSimpleFeature>;
25
+ };
26
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AACzD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,qBAAqB,CAAA;AAE7C,MAAM,MAAM,uBAAuB,GAAG,EAAE,EAAE,EAAE,CAAA;AAE5C,MAAM,MAAM,yBAAyB,GAAG;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAAA;AAEX,MAAM,MAAM,mBAAmB,GAAG;IACjC,KAAK,EAAE,CAAC,CAAA;IACR,IAAI,EAAE,CAAC,CAAA;IACP,OAAO,EAAE,CAAC,CAAA;CACV,CAAA;AAED,MAAM,WAAW,eAAe;IAC/B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,mBAAmB,CAAC,MAAM,mBAAmB,CAAC,CAAA;IACpD,UAAU,EAAE,yBAAyB,CAAA;IACrC,QAAQ,EAAE,uBAAuB,CAAA;CACjC;AAED,MAAM,MAAM,UAAU,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,SAAS,CAAC,eAAe,CAAC,CAAA;CACpC,CAAA"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import type { VtPbfLayer } from "./types";
2
+ /**
3
+ * Write Vector Tile Layers to a PBF buffer
4
+ */
5
+ export default function writeVtPbf(layers: VtPbfLayer[]): ArrayBuffer;
6
+ //# sourceMappingURL=write-vt-pbf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-vt-pbf.d.ts","sourceRoot":"","sources":["../src/write-vt-pbf.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,SAAS,CAAA;AAU1D;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,GAKxB,WAAW,CACzC"}
@@ -0,0 +1,135 @@
1
+ import Pbf from "pbf";
2
+ /**
3
+ * Write Vector Tile Layers to a PBF buffer
4
+ */
5
+ export default function writeVtPbf(layers) {
6
+ const pbf = new Pbf();
7
+ for (const layer of layers) {
8
+ pbf.writeMessage(3, writeLayer, layer);
9
+ }
10
+ return pbf.finish().buffer;
11
+ }
12
+ function writeLayer(layer, pbf) {
13
+ pbf.writeVarintField(15, layer.version ?? 1);
14
+ pbf.writeStringField(1, layer.name ?? "");
15
+ pbf.writeVarintField(5, layer.extent ?? 4096);
16
+ let context;
17
+ for (const feature of layer.features) {
18
+ if (!context) {
19
+ context = {
20
+ feature,
21
+ keys: [],
22
+ values: [],
23
+ keycache: {},
24
+ valuecache: {},
25
+ };
26
+ }
27
+ else {
28
+ context.feature = feature;
29
+ }
30
+ pbf.writeMessage(2, writeFeature, context);
31
+ }
32
+ if (!context)
33
+ return;
34
+ context.keys.forEach((key) => {
35
+ pbf.writeStringField(3, key);
36
+ });
37
+ context.values.forEach((value) => {
38
+ pbf.writeMessage(4, writeValue, value);
39
+ });
40
+ }
41
+ function writeFeature(ctx, pbf) {
42
+ if (ctx.feature.id !== undefined) {
43
+ pbf.writeVarintField(1, ctx.feature.id);
44
+ }
45
+ pbf.writeMessage(2, writeProperties, ctx);
46
+ pbf.writeVarintField(3, ctx.feature.type);
47
+ pbf.writeMessage(4, writeGeometry, ctx.feature);
48
+ }
49
+ function writeProperties(ctx, pbf) {
50
+ Object.entries(ctx.feature.properties).forEach(([key, value]) => {
51
+ let keyIndex = ctx.keycache[key];
52
+ if (value === null)
53
+ return; // don't encode null value properties
54
+ if (typeof keyIndex === "undefined") {
55
+ ctx.keys.push(key);
56
+ keyIndex = ctx.keys.length - 1;
57
+ ctx.keycache[key] = keyIndex;
58
+ }
59
+ pbf.writeVarint(keyIndex);
60
+ const type = typeof value;
61
+ const valueStr = type !== "string" && type !== "boolean" && type !== "number"
62
+ ? JSON.stringify(value)
63
+ : value;
64
+ const valueKey = `${type}:${valueStr}`;
65
+ let valueIndex = ctx.valuecache[valueKey];
66
+ if (typeof valueIndex === "undefined") {
67
+ ctx.values.push(value);
68
+ valueIndex = ctx.values.length - 1;
69
+ ctx.valuecache[valueKey] = valueIndex;
70
+ }
71
+ pbf.writeVarint(valueIndex);
72
+ });
73
+ }
74
+ function command(cmd, length) {
75
+ return (length << 3) + (cmd & 0x7);
76
+ }
77
+ function zigzag(num) {
78
+ return (num << 1) ^ (num >> 31);
79
+ }
80
+ function writeGeometry(feature, pbf) {
81
+ const type = feature.type;
82
+ let x = 0;
83
+ let y = 0;
84
+ feature.geometry.forEach((ring) => {
85
+ let count = 1;
86
+ if (type === 1) {
87
+ count = ring.length;
88
+ }
89
+ pbf.writeVarint(command(1, count)); // moveto
90
+ // do not write polygon closing path as lineto
91
+ const lineCount = type === 3 ? ring.length - 1 : ring.length;
92
+ ring.forEach((xy, i) => {
93
+ if (i >= lineCount)
94
+ return;
95
+ if (i === 1 && type !== 1) {
96
+ pbf.writeVarint(command(2, lineCount - 1)); // lineto
97
+ }
98
+ const dx = xy[0] - x;
99
+ const dy = xy[1] - y;
100
+ pbf.writeVarint(zigzag(dx));
101
+ pbf.writeVarint(zigzag(dy));
102
+ x += dx;
103
+ y += dy;
104
+ });
105
+ if (type === 3) {
106
+ pbf.writeVarint(command(7, 1)); // closepath
107
+ }
108
+ });
109
+ }
110
+ function writeValue(value, pbf) {
111
+ if (typeof value === "string") {
112
+ pbf.writeStringField(1, value);
113
+ }
114
+ else if (typeof value === "boolean") {
115
+ pbf.writeBooleanField(7, value);
116
+ }
117
+ else if (typeof value === "number") {
118
+ if (!Number.isFinite(value)) {
119
+ pbf.writeDoubleField(3, value);
120
+ }
121
+ else if (value % 1 !== 0) {
122
+ pbf.writeDoubleField(3, value);
123
+ }
124
+ else if (!Number.isSafeInteger(value)) {
125
+ pbf.writeDoubleField(3, value);
126
+ }
127
+ else if (value < 0) {
128
+ pbf.writeSVarintField(6, value);
129
+ }
130
+ else {
131
+ pbf.writeVarintField(5, value);
132
+ }
133
+ }
134
+ }
135
+ //# sourceMappingURL=write-vt-pbf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-vt-pbf.js","sourceRoot":"","sources":["../src/write-vt-pbf.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "@osmix/vt",
4
4
  "type": "module",
5
- "version": "0.0.1",
5
+ "version": "0.0.2",
6
6
  "description": "Encode Osmix binary overlay tiles directly into Mapbox Vector Tiles",
7
7
  "main": "./src/index.ts",
8
8
  "publishConfig": {
@@ -33,6 +33,7 @@
33
33
  "sideEffects": false,
34
34
  "scripts": {
35
35
  "build": "tsc",
36
+ "prepublishOnly": "tsc",
36
37
  "test": "vitest",
37
38
  "typecheck": "tsc --noEmit"
38
39
  },
@@ -44,6 +45,7 @@
44
45
  "devDependencies": {
45
46
  "@mapbox/vector-tile": "^2.0.4",
46
47
  "@osmix/core": "workspace:*",
48
+ "@types/node": "catalog:",
47
49
  "typescript": "catalog:",
48
50
  "vitest": "catalog:"
49
51
  }
package/src/encode.ts CHANGED
@@ -43,8 +43,8 @@ export function projectToTile(
43
43
  }
44
44
 
45
45
  export class OsmixVtEncoder {
46
- private readonly nodeLayerName: string
47
- private readonly wayLayerName: string
46
+ readonly nodeLayerName: string
47
+ readonly wayLayerName: string
48
48
  private readonly osmix: Osmix
49
49
  private readonly extent: number
50
50
  private readonly extentBbox: [number, number, number, number]
@@ -64,7 +64,6 @@ export class OsmixVtEncoder {
64
64
 
65
65
  getTile(tile: Tile): ArrayBuffer {
66
66
  const sm = new SphericalMercatorTile({ size: this.extent, tile })
67
- // const proj = projectToTile(tile, this.extent)
68
67
  const bbox = sm.bbox(tile[0], tile[1], tile[2]) as GeoBbox2D
69
68
  return this.getTileForBbox(bbox, (ll) => sm.llToTilePx(ll))
70
69
  }