Uh oh!
There was an error while loading. Please reload this page.
feat: footprint to tiles (MAPCO-11173) - #101
Conversation
🎫 Related Jira Issue: MAPCO-11173 |
Hi it is me, your friendly bot helper! 👋 {
"dependencies": {
"@map-colonies/mc-utils": "https://ghatmpstorage.blob.core.windows.net/npm-packages/mc-utils-17f19b20fd2f25603e53a41c4714aa53f7e58b5d.tgz"
}
}The link will expire in a week ⌛ |
Hi it is me, your friendly bot helper! 👋 {
"dependencies": {
"@map-colonies/mc-utils": "https://ghatmpstorage.blob.core.windows.net/npm-packages/mc-utils-279776e6c098547223caa3e89941eb1a2db6650c.tgz"
}
}The link will expire in a week ⌛ |
CL-SHLOMIKONCHA
left a comment
There was a problem hiding this comment.
as we discussed, change the span word to more meaningful name, once for zoomRange and once for degreePerTile
| // bounds of a tile on the WGS84 geodetic grid: tiles span 180 / 2^z degrees, origin at the | ||
| // south-west corner (-180, -90), x grows east (two hemispheres wide), y grows north | ||
| function tileBounds(zoom: number, x: number, y: number): TileBounds { | ||
| const span = degreesPerTile(zoom); |
There was a problem hiding this comment.
please change span to more meaningful const name
| // emits the whole subtree of a tile proven fully inside the footprint — pure arithmetic, | ||
| // no geometry tests: a coarse interior tile can stand in for millions of deep tiles | ||
| function* subtreeRanges(zoom: number, x: number, y: number, span: ZoomRange): Generator<ITileRange> { |
There was a problem hiding this comment.
also span here, zoomRange
| // no edges cross + center inside -> whole subtree is inside: emit it arithmetically | ||
| // no edges cross + center outside -> whole subtree is outside: prune it | ||
| // edges cross -> the tile intersects: emit it, recurse into 4 children | ||
| function* descend(zoom: number, x: number, y: number, edges: Segment[], rings: Position[][], span: ZoomRange): Generator<ITileRange> { |
Hi it is me, your friendly bot helper! 👋 {
"dependencies": {
"@map-colonies/mc-utils": "https://ghatmpstorage.blob.core.windows.net/npm-packages/mc-utils-f0a390c9448582b50cccab53a5b25e9963ccd25e.tgz"
}
}The link will expire in a week ⌛ |
Hi it is me, your friendly bot helper! 👋 {
"dependencies": {
"@map-colonies/mc-utils": "https://ghatmpstorage.blob.core.windows.net/npm-packages/mc-utils-594e87195f23d153b8b6619e3e69c3f3bf247b0f.tgz"
}
}The link will expire in a week ⌛ |
Hi it is me, your friendly bot helper! 👋 {
"dependencies": {
"@map-colonies/mc-utils": "https://ghatmpstorage.blob.core.windows.net/npm-packages/mc-utils-b961d49970bde77824b53dc5fb98144fe42f4ef8.tgz"
}
}The link will expire in a week ⌛ |
Further information:
Adds a new geometry-only API that computes, for a footprint (Polygon / MultiPolygon / Feature, holes supported) and an inclusive zoom span, all intersecting tiles on the WGS84 geodetic 2:1 grid — emitted lazily as compressed ITileRanges.
How the algorithm works:
The tile pyramid is a quadtree: tile (z, x, y) contains exactly tiles (z+1, 2x..2x+1, 2y..2y+1), so classifying one coarse tile can settle its entire subtree. Starting from the grid's two zoom-0 root tiles, each visited tile is classified by filtering the footprint's edge list against its bounds (Liang-Barsky clipping):
Recursion therefore only follows the footprint's boundary: total geometry work is O(boundary tiles at maxZoom) instead of O(bbox area × zoom levels). Interior bulk and exterior bulk are both settled at the coarsest possible level, which is also why memory stays flat — interior subtrees never get expanded, they're expressed as ranges. Point-in-polygon uses the even-odd ray-casting rule, which makes holes and MultiPolygon parts work with no special casing.