@truelies/osm-dybuf 0.4.6 → 0.4.7

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/README.md CHANGED
@@ -95,6 +95,7 @@ import {
95
95
  CANONICAL_CODE_LEVEL,
96
96
  gridexAtLonLat,
97
97
  gridCodeAtLonLat,
98
+ gridCodeNeighbors,
98
99
  gridCodeComponentsAtLonLat,
99
100
  lonCodeFromLondex,
100
101
  latCodeFromLatdex,
@@ -124,6 +125,7 @@ const lonCode = lonCodeFromLondex(16, -123);
124
125
  const latCode = latCodeFromLatdex(16, 456);
125
126
  console.log(lonCode, latCode);
126
127
  console.log(gridCodeAtLonLat(16, 121.56, 25.03));
128
+ console.log(gridCodeNeighbors(9, gridCodeAtLonLat(9, 121.56, 25.03)));
127
129
 
128
130
  // canonical prefix / range for coarser level query
129
131
  const lonPrefix = londexPrefixCodeFromLonCode(15, lonCode, CANONICAL_CODE_LEVEL);
@@ -154,6 +156,10 @@ console.log(decodeAxisCode(axisCode, lonBits)); // -123
154
156
  - expands any `lv <= sourceLevel` cell into the corresponding canonical axis-code range
155
157
  - `gridCodeAtLonLat(level, lon, lat)` / `gridCodeFromGridex(level, gridex)`:
156
158
  - returns the packed `gridCode`
159
+ - `GridUnit.neighbors(gridex)` / `gridexNeighbors(level, gridex, radius?)` / `gridCodeNeighbors(level, gridCode, radius?)`:
160
+ - returns one-ring neighbors for an existing cell/code
161
+ - currently only supports `radius=1`
162
+ - crosses the zero axis without returning zero-index cells; longitude wraps and latitude clamps at poles
157
163
  - `encodeAxisCode(index, magnitudeBits)` / `decodeAxisCode(code, magnitudeBits)`:
158
164
  - encodes grid index as `sign bit + (abs(index) - 1)`
159
165
 
package/grid_index.d.ts CHANGED
@@ -33,6 +33,7 @@ export declare class GridUnit {
33
33
  makeGridex(londex: number, latdex: number): GridexAtLv;
34
34
  gridexesAt(longitudeInt: number, latitudeInt: number): GridexAtLv[];
35
35
  gridexesWithExt(longitudeInt: number, latitudeInt: number, ext?: number): GridexAtLv[];
36
+ neighbors(gridex: Gridex, includeSelf?: boolean): GridexAtLv[];
36
37
  toLowerLevelGridexes(gridex: Gridex): GridexAtLv[];
37
38
  toUpperLevelGridex(gridex: Gridex): GridexAtLv;
38
39
  boundsOfGridFine(gridex: Gridex, applyTriangle?: boolean): [number, number, number, number];
@@ -102,6 +103,8 @@ export declare function lonLatCodesFromGridCode(
102
103
  };
103
104
  export declare function gridCodeFromGridex(level: number, gridex: Gridex | number, latdex?: number): number;
104
105
  export declare function gridexFromGridCode(level: number, gridCode: number): GridexAtLv;
106
+ export declare function gridexNeighbors(level: number, gridex: Gridex, radius?: number): GridexAtLv[];
107
+ export declare function gridCodeNeighbors(level: number, gridCode: number, radius?: number): number[];
105
108
  export declare function gridCodeAtLonLat(level: number, longitude: number, latitude: number): number;
106
109
  export declare function gridCodeComponentsAtLonLat(
107
110
  level: number,
package/grid_index.mjs CHANGED
@@ -159,6 +159,52 @@ export class GridUnit {
159
159
  return result;
160
160
  }
161
161
 
162
+ _neighborAxisIndices(index, axis) {
163
+ const min = axis === "lon" ? this.minLondex : this.minLatdex;
164
+ const max = axis === "lon" ? this.maxLondex : this.maxLatdex;
165
+
166
+ const prev = () => {
167
+ if (index === min) return axis === "lon" ? max : min;
168
+ if (index === 1) return -1;
169
+ return index - 1;
170
+ };
171
+ const next = () => {
172
+ if (index === max) return axis === "lon" ? min : max;
173
+ if (index === -1) return 1;
174
+ return index + 1;
175
+ };
176
+
177
+ return [...new Set([prev(), index, next()])];
178
+ }
179
+
180
+ neighbors(gridex, includeSelf = false) {
181
+ if (!Number.isInteger(gridex.londex) || !Number.isInteger(gridex.latdex)) {
182
+ throw new Error("neighbors expects a Gridex-like object");
183
+ }
184
+ if (gridex.londex === 0 || gridex.latdex === 0) {
185
+ throw new Error("gridex indices must be non-zero");
186
+ }
187
+ if (gridex.londex < this.minLondex || gridex.londex > this.maxLondex) {
188
+ throw new Error(`londex out of range for level ${this.level}: ${gridex.londex}`);
189
+ }
190
+ if (gridex.latdex < this.minLatdex || gridex.latdex > this.maxLatdex) {
191
+ throw new Error(`latdex out of range for level ${this.level}: ${gridex.latdex}`);
192
+ }
193
+
194
+ const lonIndices = this._neighborAxisIndices(gridex.londex, "lon");
195
+ const latIndices = this._neighborAxisIndices(gridex.latdex, "lat");
196
+ const result = [];
197
+ for (const londex of lonIndices) {
198
+ for (const latdex of latIndices) {
199
+ if (!includeSelf && londex === gridex.londex && latdex === gridex.latdex) {
200
+ continue;
201
+ }
202
+ result.push(this.makeGridex(londex, latdex));
203
+ }
204
+ }
205
+ return result;
206
+ }
207
+
162
208
  toLowerLevelGridexes(gridex) {
163
209
  if (this.level >= MAX_LEVEL) {
164
210
  throw new Error(`No lower level exists for level ${this.level}`);
@@ -420,6 +466,23 @@ export function gridexFromGridCode(level, gridCode) {
420
466
  );
421
467
  }
422
468
 
469
+ function ensureSingleNeighborRadius(radius) {
470
+ if (radius !== 1) {
471
+ throw new Error("Only radius=1 is currently supported");
472
+ }
473
+ }
474
+
475
+ export function gridexNeighbors(level, gridex, radius = 1) {
476
+ ensureSingleNeighborRadius(radius);
477
+ return new GridUnit(level).neighbors(gridex);
478
+ }
479
+
480
+ export function gridCodeNeighbors(level, gridCode, radius = 1) {
481
+ ensureSingleNeighborRadius(radius);
482
+ return gridexNeighbors(level, gridexFromGridCode(level, gridCode), radius)
483
+ .map((neighbor) => gridCodeFromGridex(level, neighbor));
484
+ }
485
+
423
486
  export function gridCodeAtLonLat(level, longitude, latitude) {
424
487
  const gridex = gridexAtLonLat(level, longitude, latitude);
425
488
  return gridCodeFromGridex(level, gridex);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truelies/osm-dybuf",
3
- "version": "0.4.6",
3
+ "version": "0.4.7",
4
4
  "description": "Gridex OSM DyBuf parser and schema utilities",
5
5
  "type": "module",
6
6
  "main": "./osm_dybuf.mjs",