{"_id":"@bitruvius/geo-core","_rev":"6-f5788659d66190bf3320aa2d745a56d1","name":"@bitruvius/geo-core","dist-tags":{"latest":"0.3.2"},"versions":{"0.3.1":{"name":"@bitruvius/geo-core","version":"0.3.1","keywords":["bitruvius","geospatial","webgl2","sdk","contracts","mercator","ecef"],"license":"SEE LICENSE IN LICENSE","_id":"@bitruvius/geo-core@0.3.1","maintainers":[{"name":"geoffhtaylor3d","email":"geoffhtaylor3d@gmail.com"},{"name":"danrhedges","email":"danrhedges@gmail.com"}],"homepage":"https://dev.bitruvius.com/sdks/js/","bugs":{"url":"https://github.com/bitruvius/support"},"dist":{"shasum":"80fcf5a6c68d0eb1aff726aa62c870f97f55b096","tarball":"https://registry.npmjs.org/@bitruvius/geo-core/-/geo-core-0.3.1.tgz","fileCount":31,"integrity":"sha512-RraxF//AFAT7dH/Y7Us1wgx8NfXnilq40mVJov23kV3JX2rRpFbdDPVgRh3U1GrzEoINJPiQ9fxUuyJwCR205Q==","signatures":[{"sig":"MEYCIQCIZVT4sfwLd1Og/DJwXrKSNunZZDXtmO5UsJmrJ4tlfQIhAIdFQIsKoSLd3AxAJUacvRoML2qrppXIPVwouw5MXGgf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":188175},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","shasum":"80fcf5a6c68d0eb1aff726aa62c870f97f55b096","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"test":"bun test","build":"bun build ./src/index.ts --outdir dist --format esm --target browser --minify --external '@bitruvius/*' && tsc --emitDeclarationOnly"},"_npmUser":{"name":"geoffhtaylor3d","email":"geoffhtaylor3d@gmail.com"},"_integrity":"sha512-RraxF//AFAT7dH/Y7Us1wgx8NfXnilq40mVJov23kV3JX2rRpFbdDPVgRh3U1GrzEoINJPiQ9fxUuyJwCR205Q==","_npmVersion":"10.8.3","description":"Bitruvius geospatial SDK core: decoder/renderer/viewer-adapter contracts, geospatial math (ENU/ECEF/mercator), map-style expressions, and the dequantization reference. Builds on @bitruvius/foundation.","directories":{},"sideEffects":["./src/index.ts"],"_nodeVersion":"24.3.0","dependencies":{"@bitruvius/foundation":"^0.3.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/geo-core_0.3.1_1785725501813_0.7064879466019149","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"name":"@bitruvius/geo-core","version":"0.3.2","description":"Bitruvius geospatial SDK core: decoder/renderer/viewer-adapter contracts, geospatial math (ENU/ECEF/mercator), map-style expressions, and the dequantization reference. Builds on @bitruvius/foundation.","type":"module","license":"SEE LICENSE IN LICENSE","bugs":{"url":"https://github.com/bitruvius/support"},"homepage":"https://dev.bitruvius.com/sdks/js/","keywords":["bitruvius","geospatial","webgl2","sdk","contracts","mercator","ecef"],"sideEffects":["./src/index.ts"],"engines":{"node":">=18"},"main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"publishConfig":{"access":"public"},"scripts":{"build":"bun build ./src/index.ts --outdir dist --format esm --target browser --minify --external '@bitruvius/*' && tsc --emitDeclarationOnly","test":"bun test"},"dependencies":{"@bitruvius/foundation":"^0.3.2"},"_id":"@bitruvius/geo-core@0.3.2","_integrity":"sha512-SDDhDZ4uuvyFHDlL31Gn39SG/I79rrkcBjVWNMm1Mu3bZoO6dLzwnMab6sgkpwDX6VCQZtm6Qk0fuSrb4PRgdA==","_nodeVersion":"24.3.0","_npmVersion":"10.8.3","shasum":"c307f8f6b8cd1abb7004ef67f460822325956386","dist":{"integrity":"sha512-SDDhDZ4uuvyFHDlL31Gn39SG/I79rrkcBjVWNMm1Mu3bZoO6dLzwnMab6sgkpwDX6VCQZtm6Qk0fuSrb4PRgdA==","shasum":"c307f8f6b8cd1abb7004ef67f460822325956386","tarball":"https://registry.npmjs.org/@bitruvius/geo-core/-/geo-core-0.3.2.tgz","fileCount":31,"unpackedSize":188175,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCYms/h1eiOHp7gtpawJgfeNcAo4lOH9ODnuVaMIKYs8AIgCm8Rcluna1IUaQgEvl07nMV4PLq50h3TSwF3odKBNY0="}]},"_npmUser":{"name":"geoffhtaylor3d","email":"geoffhtaylor3d@gmail.com"},"directories":{},"maintainers":[{"name":"geoffhtaylor3d","email":"geoffhtaylor3d@gmail.com"},{"name":"danrhedges","email":"danrhedges@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/geo-core_0.3.2_1785952471705_0.5590977762841629"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-03T02:51:41.572Z","modified":"2026-08-05T17:54:31.991Z","0.1.0":"2026-07-24T21:35:27.214Z","0.3.0":"2026-08-03T01:27:10.713Z","0.3.1":"2026-08-03T02:51:41.950Z","0.3.2":"2026-08-05T17:54:31.841Z"},"bugs":{"url":"https://github.com/bitruvius/support"},"license":"SEE LICENSE IN LICENSE","homepage":"https://dev.bitruvius.com/sdks/js/","keywords":["bitruvius","geospatial","webgl2","sdk","contracts","mercator","ecef"],"description":"Bitruvius geospatial SDK core: decoder/renderer/viewer-adapter contracts, geospatial math (ENU/ECEF/mercator), map-style expressions, and the dequantization reference. Builds on @bitruvius/foundation.","maintainers":[{"name":"geoffhtaylor3d","email":"geoffhtaylor3d@gmail.com"},{"name":"danrhedges","email":"danrhedges@gmail.com"}],"readme":"<p align=\"center\">\n  <a href=\"https://bitruvius.com\"><img src=\"https://cdn.bitruvius.com/brand/bitruvius-logo.png\" width=\"360\" alt=\"Bitruvius\"></a>\n</p>\n\n# @bitruvius/geo-core\n\n**The contracts and geospatial math every Bitruvius package shares, in pure TypeScript with no GPU, wasm or DOM.**\n\n> **Internal building block.** This package exists so that\n> [`@bitruvius/sdk-maplibre`](https://www.npmjs.com/package/@bitruvius/sdk-maplibre) and the\n> Bitruvius codecs can resolve their dependencies on npm. It has no standalone product story.\n> Unless you are deliberately building against it, install the SDK instead.\n\n## Why it is a separate package\n\nThe SDK is assembled from packages that must not know about each other. A codec must not\ndepend on a streaming engine. An engine must not depend on a codec. A renderer must not\ndepend on a viewer. Each of those boundaries is an interface, and an interface has to live\nsomewhere both sides can import it from without importing each other. That is this package.\n\nThe seams are real, not theoretical:\n\n- `@bitruvius/turbo-lepcc` and `@bitruvius/bvc` both implement `I3sPointCloudDecoder`.\n  The `@bitruvius/i3s` engine imports the interface and never a codec, so you swap LEPCC for\n  BVC without touching streaming or rendering.\n- `@bitruvius/draco`, `@bitruvius/meshopt` and `@bitruvius/ktx2` implement\n  `DracoGeometryDecoder`, `MeshoptDecoder` and `Ktx2Transcoder`. They are injected into\n  `@bitruvius/gltf`, which is why a codec package depends on geo-core and never on the parser.\n- The renderers (`splats`, `ptcloud`, `mesh`, `point-symbols`, `raster`) are driven entirely\n  through `ViewerAdapter` and `FrameState`. They do not know MapLibre exists. A new host is\n  one adapter file, not a renderer fork.\n\nThe second reason is purity. Nothing here touches WebGL, wasm or the DOM, so the same code\nruns on the main thread, inside a decode worker, and under `bun test` with no browser. That\nis a requirement, not a preference: the worker packs a tile into the shared ENU grid, the\nshader expands it back, and the tests prove the two agree. Both sides have to be reading\nthe same arithmetic from the same file.\n\nTwenty other packages in this repository depend on geo-core. It depends on one thing,\n[`@bitruvius/foundation`](https://www.npmjs.com/package/@bitruvius/foundation).\n\n## What is in it\n\n**Contracts.** `Decoder` and `DecoderFactory`, `Renderer` and `TileHandle`, `ViewerAdapter`\nand `FrameState`, plus the per-format decode seams: `GltfSplatDecoder`,\n`I3sPointCloudDecoder`, `I3sMeshDecoder`, `CesiumPointDecoder`, `MeshTileDecoder`.\n\n**The decoded model.** `DecodedSplatTile`, `DecodedPointTile` and `ContainerMeta` carry\nquantized structure-of-arrays straight out of the decoder, because dequantization is\ndeferred to the render shaders. `PackedPointTile` and `PackedMeshTile` are the ENU-rebased,\nGPU-ready forms the renderers upload. No floating-point geometry crosses this boundary.\n\n**Geospatial math.** WGS84 geodetic to ECEF and back (Bowring closed form), ECEF to ENU,\nand Web Mercator implemented from the public definition to match MapLibre's\n`MercatorCoordinate` exactly, so this math is interchangeable with the viewer's own.\nColumn-major `mat4`/`mat3` and planes for frustum culling and clipping.\n\n**Measurement.** What the SDK's measure tools are built on: slope and horizontal\ndistance, bearing, polyline length, polygon area and perimeter, the sampling grid behind\ncut-and-fill volume, and contour extraction. These solve in the ENU tangent plane at the\nfeature being measured rather than on the ellipsoid, which is exact at city scale and\nstarts to drift past roughly 50 km; `haversineDistance` on the mean sphere is the\nlong-range cross-check and the axis measure for elevation profiles.\n\n**Packing.** `packPointTileEnu`, `packI3sPointsEnu`, `packGltfPointsEnu` and `packMeshEnu`\nrebase a decoded tile into the shared ENU meters frame and requantize it onto the\nrenderer's integer grid, so coordinates stay f32-exact however far the dataset sits from\nthe scene anchor. `extractHardEdges` derives the lines a person would draw if asked to\nsketch a building, since no I3S or 3D Tiles service ships edge geometry.\n\n**Placement.** `ModelPlacement` is the vocabulary the single-model layers expose: `upAxis`\npreset, `heading`/`pitch`/`roll` in degrees, `scale`, `anchorPoint`. `placementBasis` and\n`modelPlacementMatrix` compose the correct basis, including the mercator Y-flip that users\nmust never see. `QuantBoundsAccumulator` derives source-space bounds from streamed\nquantized tiles, with robust percentiles, because splat captures arrive wrapped in a halo\nof far-field background outliers that would otherwise hold the bounding box hostage.\n\n**Style and metadata.** `compileSqlFilter` (Esri Building Scene Layer `filterExpression`)\nand `compileStyleExpression` (3D Tiles declarative styling) compile to one AST and one\nclosure, evaluated per feature against a `PropertyGetter`. Hand-written tokenizer and\nrecursive-descent parser, no `eval`. I3S attributes, 3D Tiles batch tables and glTF\n`EXT_structural_metadata` property tables all normalize into the same feature columns.\n\n**Dequant reference.** The canonical inverse-quantization formulas. The GLSL shaders port\nthese functions, and this module is the parity oracle they are tested against.\n\nBecause geo-core re-exports `@bitruvius/foundation`, importing it also gives you the\ndomain-agnostic base: `TaskQueue`, `WorkerPool`, `detectCapabilities`,\n`recommendDecodeBackend`, SDK config and `BitruviusError`.\n\n```ts\nimport { placementMatrix, toFloat32 } from '@bitruvius/geo-core';\n\nconst model = placementMatrix({ lng: -73.99, lat: 40.75, altitude: 0 });\ngl.uniformMatrix4fv(uModel, false, toFloat32(model));\n```\n\n## Should you depend on it directly\n\nUsually not. Install [`@bitruvius/sdk-maplibre`](https://www.npmjs.com/package/@bitruvius/sdk-maplibre)\nand you get this package as a transitive dependency.\n\nDepend on it directly when you are implementing one of its seams: a decoder for your own\ncontainer format that an SDK engine should stream, or a `ViewerAdapter` for a host the SDK\ndoes not ship. Those are the cases where you want the interface and nothing else.\n\nIt is published for that purpose, not as a general-purpose geospatial math library. The API\ntracks what the SDK needs and moves with SDK releases.\n\n```sh\nnpm i @bitruvius/geo-core\n```\n\n## Trademarks\n\nEsri, ArcGIS, I3S and LEPCC are trademarks of Environmental Systems Research Institute, Inc.\nCesium and 3D Tiles are trademarks of Cesium GS, Inc. Khronos, glTF and KTX are trademarks\nof The Khronos Group Inc. Google and Draco are trademarks of Google LLC. Niantic and SPZ are\ntrademarks of Niantic, Inc. MapLibre is a trademark of the MapLibre organization. All other\nmarks are the property of their respective owners.\n\nThese names are used solely to describe the data formats this software interoperates with.\nWebGL is a trademark of The Khronos Group Inc.\n\nBitruvius is not affiliated with, sponsored by, or endorsed by any of them, and no such\nrelationship is implied.\n\n## License\n\nProprietary. The full terms ship as `LICENSE` inside this package, and are readable\nbefore installing at [cdn.bitruvius.com/legal/sdk-license-v1.txt](https://cdn.bitruvius.com/legal/sdk-license-v1.txt).\n\n© Bitruvius, Inc.\n","readmeFilename":"README.md"}