@osmix/core 0.1.10 → 0.2.0
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 +25 -0
- package/LICENSE +21 -0
- package/README.md +86 -69
- package/dist/contracts.d.ts +26 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +1 -0
- package/dist/contracts.js.map +1 -0
- package/dist/entities.d.ts +1 -1
- package/dist/entities.d.ts.map +1 -1
- package/dist/entities.js +2 -7
- package/dist/entities.js.map +1 -1
- package/dist/ids.d.ts +2 -0
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +23 -15
- package/dist/ids.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/mocks.d.ts.map +1 -1
- package/dist/mocks.js.map +1 -1
- package/dist/nodes.d.ts +9 -3
- package/dist/nodes.d.ts.map +1 -1
- package/dist/nodes.js +6 -13
- package/dist/nodes.js.map +1 -1
- package/dist/osm.d.ts +1 -1
- package/dist/osm.d.ts.map +1 -1
- package/dist/osm.js +1 -4
- package/dist/osm.js.map +1 -1
- package/dist/relations.d.ts +3 -2
- package/dist/relations.d.ts.map +1 -1
- package/dist/relations.js +15 -9
- package/dist/relations.js.map +1 -1
- package/dist/stringtable.d.ts.map +1 -1
- package/dist/stringtable.js +4 -13
- package/dist/stringtable.js.map +1 -1
- package/dist/tags.d.ts +1 -1
- package/dist/tags.d.ts.map +1 -1
- package/dist/tags.js.map +1 -1
- package/dist/typed-arrays.d.ts.map +1 -1
- package/dist/typed-arrays.js.map +1 -1
- package/dist/ways.d.ts +2 -1
- package/dist/ways.d.ts.map +1 -1
- package/dist/ways.js +18 -18
- package/dist/ways.js.map +1 -1
- package/package.json +46 -31
- package/src/contracts.ts +28 -0
- package/src/entities.ts +179 -194
- package/src/ids.ts +228 -235
- package/src/index.ts +12 -9
- package/src/mocks.ts +114 -113
- package/src/nodes.ts +364 -397
- package/src/osm.ts +196 -207
- package/src/relations.ts +530 -558
- package/src/stringtable.ts +174 -183
- package/src/tags.ts +263 -271
- package/src/typed-arrays.ts +184 -194
- package/src/types/geoflatbush.d.ts +28 -33
- package/src/types/geokdbush.d.ts +28 -33
- package/src/types/kdbush.d.ts +34 -34
- package/src/ways.ts +381 -405
- package/test/ids.bench.ts +29 -0
- package/test/ids.test.ts +84 -0
- package/test/memory.test.ts +29 -30
- package/test/relations.bench.ts +27 -0
- package/test/relations.test.ts +101 -0
- package/test/tags-search.test.ts +76 -56
- package/test/typed-arrays.test.ts +100 -99
- package/tsconfig.build.json +6 -6
- package/tsconfig.json +7 -7
package/src/osm.ts
CHANGED
|
@@ -1,222 +1,211 @@
|
|
|
1
|
-
import type { OsmPbfHeaderBlock } from "@osmix/pbf"
|
|
2
|
-
import { ContentHasher } from "@osmix/shared/content-hasher"
|
|
3
|
-
import type { GeoBbox2D } from "@osmix/
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
1
|
+
import type { OsmPbfHeaderBlock } from "@osmix/pbf";
|
|
2
|
+
import { ContentHasher } from "@osmix/shared/content-hasher";
|
|
3
|
+
import type { GeoBbox2D } from "@osmix/types";
|
|
4
|
+
|
|
5
|
+
import { Nodes, type NodesTransferables } from "./nodes.ts";
|
|
6
|
+
import { Relations, type RelationsTransferables } from "./relations.ts";
|
|
7
|
+
import StringTable, { type StringTableTransferables } from "./stringtable.ts";
|
|
8
|
+
import type { BufferType } from "./typed-arrays.ts";
|
|
9
|
+
import { Ways, type WaysTransferables } from "./ways.ts";
|
|
9
10
|
|
|
10
11
|
export interface OsmTransferables<T extends BufferType = BufferType> {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
id: string;
|
|
13
|
+
header: OsmPbfHeaderBlock;
|
|
14
|
+
contentHash: string;
|
|
15
|
+
stringTable: StringTableTransferables<T>;
|
|
16
|
+
nodes: NodesTransferables<T>;
|
|
17
|
+
ways: WaysTransferables<T>;
|
|
18
|
+
relations: RelationsTransferables<T>;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export interface OsmInfo {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
22
|
+
id: string;
|
|
23
|
+
bbox: GeoBbox2D;
|
|
24
|
+
header: OsmPbfHeaderBlock;
|
|
25
|
+
stats: {
|
|
26
|
+
nodes: number;
|
|
27
|
+
ways: number;
|
|
28
|
+
relations: number;
|
|
29
|
+
};
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export interface OsmOptions {
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
id: string;
|
|
34
|
+
header: OsmPbfHeaderBlock;
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
/**
|
|
37
38
|
* OSM Entity Index.
|
|
38
39
|
*/
|
|
39
40
|
export class Osm {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
* @returns A hex string hash of the content.
|
|
211
|
-
*/
|
|
212
|
-
private computeContentHash(): string {
|
|
213
|
-
const hasher = new ContentHasher()
|
|
214
|
-
// Hash string table first (shared by all entities)
|
|
215
|
-
this.stringTable.updateHash(hasher)
|
|
216
|
-
// Hash each entity collection
|
|
217
|
-
this.nodes.updateHash(hasher)
|
|
218
|
-
this.ways.updateHash(hasher)
|
|
219
|
-
this.relations.updateHash(hasher)
|
|
220
|
-
return hasher.digest()
|
|
221
|
-
}
|
|
41
|
+
// Filename or ID of this OSM Entity index.
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly header: OsmPbfHeaderBlock;
|
|
44
|
+
|
|
45
|
+
// Shared string lookup table for all nodes, ways, and relations
|
|
46
|
+
readonly stringTable: StringTable;
|
|
47
|
+
readonly nodes: Nodes;
|
|
48
|
+
readonly ways: Ways;
|
|
49
|
+
readonly relations: Relations;
|
|
50
|
+
|
|
51
|
+
private indexBuilt = false;
|
|
52
|
+
private _contentHash = "";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create a new OSM Entity index.
|
|
56
|
+
*/
|
|
57
|
+
constructor(opts?: Partial<OsmOptions> | OsmTransferables | Osm) {
|
|
58
|
+
this.id = opts?.id ?? "unknown";
|
|
59
|
+
this.header = opts?.header ?? {
|
|
60
|
+
required_features: [],
|
|
61
|
+
optional_features: [],
|
|
62
|
+
};
|
|
63
|
+
if (opts && "stringTable" in opts) {
|
|
64
|
+
if (opts instanceof Osm) {
|
|
65
|
+
this.stringTable = new StringTable(opts.stringTable.transferables());
|
|
66
|
+
this.nodes = new Nodes(this.stringTable, opts.nodes.transferables());
|
|
67
|
+
this.ways = new Ways(this.stringTable, this.nodes, opts.ways.transferables());
|
|
68
|
+
this.relations = new Relations(
|
|
69
|
+
this.stringTable,
|
|
70
|
+
this.nodes,
|
|
71
|
+
this.ways,
|
|
72
|
+
opts.relations.transferables(),
|
|
73
|
+
);
|
|
74
|
+
this._contentHash = opts._contentHash;
|
|
75
|
+
this.indexBuilt = true;
|
|
76
|
+
} else {
|
|
77
|
+
this.stringTable = new StringTable(opts.stringTable);
|
|
78
|
+
this.nodes = new Nodes(this.stringTable, opts.nodes);
|
|
79
|
+
this.ways = new Ways(this.stringTable, this.nodes, opts.ways);
|
|
80
|
+
this.relations = new Relations(this.stringTable, this.nodes, this.ways, opts.relations);
|
|
81
|
+
this._contentHash = opts.contentHash;
|
|
82
|
+
this.indexBuilt = true;
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
this.stringTable = new StringTable();
|
|
86
|
+
this.nodes = new Nodes(this.stringTable);
|
|
87
|
+
this.ways = new Ways(this.stringTable, this.nodes);
|
|
88
|
+
this.relations = new Relations(this.stringTable, this.nodes, this.ways);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Build the internal indexes for all entities.
|
|
94
|
+
* Also computes the content hash after indexes are built.
|
|
95
|
+
*/
|
|
96
|
+
buildIndexes() {
|
|
97
|
+
this.stringTable.buildIndex();
|
|
98
|
+
this.nodes.buildIndex();
|
|
99
|
+
this.ways.buildIndex();
|
|
100
|
+
this.relations.buildIndex();
|
|
101
|
+
this.indexBuilt = true;
|
|
102
|
+
// Compute content hash after indexes are built
|
|
103
|
+
this._contentHash = this.computeContentHash();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check if the index is built and ready for use.
|
|
108
|
+
*/
|
|
109
|
+
isReady() {
|
|
110
|
+
return (
|
|
111
|
+
this.nodes.isReady() && this.ways.isReady() && this.relations.isReady() && this.indexBuilt
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Build spatial indexes for all entities.
|
|
117
|
+
*/
|
|
118
|
+
buildSpatialIndexes() {
|
|
119
|
+
this.nodes.buildSpatialIndex();
|
|
120
|
+
this.ways.buildSpatialIndex();
|
|
121
|
+
this.relations.buildSpatialIndex();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Check if spatial indexes have been built for all entity types.
|
|
126
|
+
*/
|
|
127
|
+
hasSpatialIndexes(): boolean {
|
|
128
|
+
return (
|
|
129
|
+
this.nodes.hasSpatialIndex() &&
|
|
130
|
+
this.ways.hasSpatialIndex() &&
|
|
131
|
+
this.relations.hasSpatialIndex()
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Get the bounding box of all entities in the OSM index.
|
|
137
|
+
*/
|
|
138
|
+
bbox(): GeoBbox2D {
|
|
139
|
+
return this.nodes.getBbox();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get information about the OSM index.
|
|
144
|
+
*/
|
|
145
|
+
info(): OsmInfo {
|
|
146
|
+
return {
|
|
147
|
+
id: this.id,
|
|
148
|
+
bbox: this.bbox(),
|
|
149
|
+
header: this.header,
|
|
150
|
+
stats: {
|
|
151
|
+
nodes: this.nodes.size,
|
|
152
|
+
ways: this.ways.size,
|
|
153
|
+
relations: this.relations.size,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get transferable objects for passing to another thread.
|
|
160
|
+
*/
|
|
161
|
+
transferables(): OsmTransferables {
|
|
162
|
+
return {
|
|
163
|
+
id: this.id,
|
|
164
|
+
header: this.header,
|
|
165
|
+
contentHash: this._contentHash,
|
|
166
|
+
stringTable: this.stringTable.transferables(),
|
|
167
|
+
nodes: this.nodes.transferables(),
|
|
168
|
+
ways: this.ways.transferables(),
|
|
169
|
+
relations: this.relations.transferables(),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get the content hash of this OSM dataset.
|
|
175
|
+
* The hash is computed when indexes are built.
|
|
176
|
+
*
|
|
177
|
+
* @returns A hex string hash uniquely identifying the content.
|
|
178
|
+
*/
|
|
179
|
+
contentHash(): string {
|
|
180
|
+
return this._contentHash;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Check if this OSM dataset has identical content to another.
|
|
185
|
+
* Uses the pre-computed content hash for fast comparison.
|
|
186
|
+
*
|
|
187
|
+
* @param other - The other Osm instance to compare with.
|
|
188
|
+
* @returns True if both datasets have identical content.
|
|
189
|
+
*/
|
|
190
|
+
isEqual(other: Osm | null | undefined): boolean {
|
|
191
|
+
if (!other) return false;
|
|
192
|
+
return this._contentHash === other._contentHash;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Compute a content hash of all underlying data.
|
|
197
|
+
* This hash uniquely identifies the dataset content regardless of metadata.
|
|
198
|
+
*
|
|
199
|
+
* @returns A hex string hash of the content.
|
|
200
|
+
*/
|
|
201
|
+
private computeContentHash(): string {
|
|
202
|
+
const hasher = new ContentHasher();
|
|
203
|
+
// Hash string table first (shared by all entities)
|
|
204
|
+
this.stringTable.updateHash(hasher);
|
|
205
|
+
// Hash each entity collection
|
|
206
|
+
this.nodes.updateHash(hasher);
|
|
207
|
+
this.ways.updateHash(hasher);
|
|
208
|
+
this.relations.updateHash(hasher);
|
|
209
|
+
return hasher.digest();
|
|
210
|
+
}
|
|
222
211
|
}
|