@bitruvius/geo-core 0.3.1
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/LICENSE +167 -0
- package/README.md +133 -0
- package/dist/contracts/cesium-point-decoder.d.ts +34 -0
- package/dist/contracts/decoder.d.ts +191 -0
- package/dist/contracts/feature-metadata.d.ts +161 -0
- package/dist/contracts/gltf-splat-decoder.d.ts +53 -0
- package/dist/contracts/i3s-mesh-decoder.d.ts +80 -0
- package/dist/contracts/i3s-point-decoder.d.ts +90 -0
- package/dist/contracts/mesh-codecs.d.ts +135 -0
- package/dist/contracts/mesh.d.ts +304 -0
- package/dist/contracts/renderer.d.ts +34 -0
- package/dist/contracts/viewer-adapter.d.ts +68 -0
- package/dist/dequant/formulas.d.ts +93 -0
- package/dist/dequant/stray-cull.d.ts +29 -0
- package/dist/dequant/tile-bounds.d.ts +109 -0
- package/dist/geo/ecef.d.ts +70 -0
- package/dist/geo/hard-edges.d.ts +71 -0
- package/dist/geo/mat4.d.ts +115 -0
- package/dist/geo/measure.d.ts +134 -0
- package/dist/geo/mercator.d.ts +95 -0
- package/dist/geo/model-placement.d.ts +141 -0
- package/dist/geo/pack-gltf-points-enu.d.ts +41 -0
- package/dist/geo/pack-mesh-edges.d.ts +16 -0
- package/dist/geo/pack-mesh-enu.d.ts +46 -0
- package/dist/geo/pack-point-ecef.d.ts +42 -0
- package/dist/geo/pack-point-enu.d.ts +126 -0
- package/dist/geo/plane.d.ts +38 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +1 -0
- package/dist/style/expression.d.ts +122 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Bitruvius SDK License Agreement
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bitruvius, Inc. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This Bitruvius SDK License Agreement (the "Agreement") is between you and
|
|
6
|
+
Bitruvius, Inc., a Delaware corporation ("Bitruvius"), and governs the use of
|
|
7
|
+
the Bitruvius SDK, including all @bitruvius npm packages, browser bundles,
|
|
8
|
+
WebAssembly binaries, documentation, and related materials distributed with
|
|
9
|
+
this notice (collectively, the "SDK").
|
|
10
|
+
|
|
11
|
+
1. LICENSE GRANT
|
|
12
|
+
|
|
13
|
+
Subject to the terms of this Agreement, Bitruvius grants you a worldwide,
|
|
14
|
+
royalty-free, non-exclusive, non-transferable, revocable license to:
|
|
15
|
+
|
|
16
|
+
(a) use the SDK, in unmodified form, in any application, website, or
|
|
17
|
+
service you develop, whether commercial or non-commercial (an
|
|
18
|
+
"Application"); and
|
|
19
|
+
(b) reproduce and distribute the SDK solely as embedded in or bundled
|
|
20
|
+
with an Application (for example, as part of a compiled or bundled
|
|
21
|
+
build of the Application), provided the SDK is not distributed on a
|
|
22
|
+
standalone basis and remains subject to this Agreement.
|
|
23
|
+
|
|
24
|
+
2. RESTRICTIONS
|
|
25
|
+
|
|
26
|
+
Except as expressly permitted in Section 1 or by applicable law
|
|
27
|
+
notwithstanding this limitation, you may not, and may not permit or assist
|
|
28
|
+
any third party to:
|
|
29
|
+
|
|
30
|
+
(a) modify, adapt, translate, or create derivative works of the SDK;
|
|
31
|
+
(b) redistribute, publish, sublicense, sell, rent, lease, or otherwise
|
|
32
|
+
make the SDK available on a standalone basis, including republishing
|
|
33
|
+
the SDK or any portion of it to any package registry or content
|
|
34
|
+
delivery network;
|
|
35
|
+
(c) reverse engineer, decompile, disassemble, decode, or otherwise
|
|
36
|
+
attempt to derive or reconstruct the source code, underlying ideas,
|
|
37
|
+
algorithms, file formats, or non-public APIs of the SDK, including
|
|
38
|
+
the WebAssembly binaries contained in the SDK;
|
|
39
|
+
(d) use the SDK, or any output or knowledge derived from it, to develop,
|
|
40
|
+
train, or improve a product or service that competes with the SDK or
|
|
41
|
+
with Bitruvius codec technology, including implementing or
|
|
42
|
+
reimplementing encoders or decoders for Bitruvius codec formats;
|
|
43
|
+
(e) remove, obscure, or alter any copyright, license, or attribution
|
|
44
|
+
notices contained in the SDK.
|
|
45
|
+
|
|
46
|
+
THIRD-PARTY COMPONENTS. Nothing in this Section 2 limits any right granted to
|
|
47
|
+
you directly by a third party under the license covering a third-party
|
|
48
|
+
component distributed with the SDK. Those components and their licenses are
|
|
49
|
+
identified in the NOTICES files distributed alongside them, together with a
|
|
50
|
+
copy of each license. Where this Agreement conflicts with such a license as
|
|
51
|
+
applied to that component, the third-party license governs that component.
|
|
52
|
+
|
|
53
|
+
THIRD-PARTY DATA AND SERVICES. The SDK is able to connect to data, imagery,
|
|
54
|
+
tilesets, and services operated by third parties, some of which require
|
|
55
|
+
credentials that you obtain in your own name. This Agreement grants you no
|
|
56
|
+
right, title, or license in or to any such data or service. Your access to and
|
|
57
|
+
use of them is governed solely by your agreement with the relevant provider,
|
|
58
|
+
including any obligation to display attribution or to restrict redistribution.
|
|
59
|
+
Bitruvius does not supply, endorse, or warrant any third-party data or service,
|
|
60
|
+
is not a party to your agreement with any provider, and bears no responsibility
|
|
61
|
+
for its availability, accuracy, terms, or charges.
|
|
62
|
+
|
|
63
|
+
3. OWNERSHIP
|
|
64
|
+
|
|
65
|
+
The SDK is licensed, not sold. Bitruvius and its licensors retain all
|
|
66
|
+
right, title, and interest in and to the SDK, including all intellectual
|
|
67
|
+
property rights. No rights are granted except as expressly set out in this
|
|
68
|
+
Agreement.
|
|
69
|
+
|
|
70
|
+
4. PRERELEASE VERSIONS
|
|
71
|
+
|
|
72
|
+
Versions of the SDK identified as alpha or beta (including any 0.x or
|
|
73
|
+
prerelease-tagged versions) are provided for evaluation and testing,
|
|
74
|
+
may change or be discontinued at any time without notice, and are provided
|
|
75
|
+
without any commitment of support or backward compatibility.
|
|
76
|
+
|
|
77
|
+
5. NO WARRANTY
|
|
78
|
+
|
|
79
|
+
THE SDK IS PROVIDED "AS IS" AND "AS AVAILABLE", WITHOUT WARRANTY OF ANY
|
|
80
|
+
KIND, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY WARRANTIES OF
|
|
81
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, OR
|
|
82
|
+
NON-INFRINGEMENT. BITRUVIUS DOES NOT WARRANT THAT THE SDK WILL BE
|
|
83
|
+
UNINTERRUPTED, ERROR-FREE, OR SECURE.
|
|
84
|
+
|
|
85
|
+
6. LIMITATION OF LIABILITY
|
|
86
|
+
|
|
87
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT WILL BITRUVIUS BE
|
|
88
|
+
LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR EXEMPLARY
|
|
89
|
+
DAMAGES, OR FOR ANY LOSS OF PROFITS, REVENUE, DATA, OR GOODWILL, ARISING
|
|
90
|
+
OUT OF OR RELATING TO THIS AGREEMENT OR THE SDK, EVEN IF ADVISED OF THE
|
|
91
|
+
POSSIBILITY OF SUCH DAMAGES. BITRUVIUS'S TOTAL AGGREGATE LIABILITY ARISING
|
|
92
|
+
OUT OF OR RELATING TO THIS AGREEMENT WILL NOT EXCEED ONE HUNDRED (100) US
|
|
93
|
+
DOLLARS.
|
|
94
|
+
|
|
95
|
+
7. INDEMNIFICATION
|
|
96
|
+
|
|
97
|
+
You will defend, indemnify, and hold harmless Bitruvius and its officers,
|
|
98
|
+
directors, employees, and agents from and against any third-party claim,
|
|
99
|
+
demand, suit, or proceeding, and any resulting losses, damages, liabilities,
|
|
100
|
+
settlements, costs, and reasonable attorneys' fees, arising out of or
|
|
101
|
+
relating to: (a) your Applications or any product or service you build with
|
|
102
|
+
or distribute using the SDK; (b) your data, content, or the services you
|
|
103
|
+
direct the SDK to access; (c) your use of the SDK in violation of this
|
|
104
|
+
Agreement or of any applicable law; or (d) your infringement or
|
|
105
|
+
misappropriation of any third party's rights. Bitruvius will notify you of
|
|
106
|
+
any such claim, allow you to control the defense (except that any settlement
|
|
107
|
+
requiring an admission or payment by Bitruvius requires its consent, not to
|
|
108
|
+
be unreasonably withheld), and provide reasonable cooperation at your
|
|
109
|
+
expense.
|
|
110
|
+
|
|
111
|
+
BITRUVIUS PROVIDES NO INDEMNITY OF ANY KIND UNDER THIS AGREEMENT, INCLUDING
|
|
112
|
+
NO DEFENSE OR INDEMNITY AGAINST ANY CLAIM THAT THE SDK INFRINGES OR
|
|
113
|
+
MISAPPROPRIATES ANY PATENT, COPYRIGHT, TRADEMARK, TRADE SECRET, OR OTHER
|
|
114
|
+
INTELLECTUAL PROPERTY RIGHT. THE SDK IS LICENSED AT NO CHARGE AND IS
|
|
115
|
+
PROVIDED WITHOUT SUCH PROTECTION. If you require an intellectual property
|
|
116
|
+
indemnity, contact legal@bitruvius.com about a commercial license; any such
|
|
117
|
+
indemnity applies only if expressly agreed in a signed written agreement.
|
|
118
|
+
|
|
119
|
+
8. TERMINATION
|
|
120
|
+
|
|
121
|
+
This Agreement is effective until terminated. It terminates automatically,
|
|
122
|
+
without notice, if you breach any of its terms. Upon termination you must
|
|
123
|
+
cease all use of the SDK and destroy all copies in your possession or
|
|
124
|
+
control, except that Applications already distributed to end users with the
|
|
125
|
+
SDK embedded may continue to be used. Sections 2, 3, 5, 6, 7, 8, and 9
|
|
126
|
+
survive termination.
|
|
127
|
+
|
|
128
|
+
9. GENERAL
|
|
129
|
+
|
|
130
|
+
This Agreement constitutes the entire agreement between you and Bitruvius
|
|
131
|
+
concerning the SDK and supersedes any prior agreements. Bitruvius may
|
|
132
|
+
publish updated or supplemental terms for future SDK versions at
|
|
133
|
+
https://bitruvius.com/eula; the terms accompanying a given SDK version
|
|
134
|
+
govern that version. If any provision of this Agreement is held
|
|
135
|
+
unenforceable, the remaining provisions remain in full force.
|
|
136
|
+
|
|
137
|
+
GOVERNING LAW AND VENUE. This Agreement is governed by and construed in
|
|
138
|
+
accordance with the laws of the State of Georgia and the applicable federal
|
|
139
|
+
law of the United States, without regard to conflict-of-law provisions, and
|
|
140
|
+
excluding the United Nations Convention on Contracts for the International
|
|
141
|
+
Sale of Goods. The exclusive venue for any dispute arising out of or
|
|
142
|
+
relating to this Agreement or the SDK is the state or federal courts located
|
|
143
|
+
in Cobb County, Georgia, and each party consents to personal jurisdiction
|
|
144
|
+
and venue in those courts.
|
|
145
|
+
|
|
146
|
+
ASSIGNMENT. You may not assign or transfer this Agreement, in whole or in
|
|
147
|
+
part, without Bitruvius's prior written consent, and any attempted
|
|
148
|
+
assignment without that consent is void. Bitruvius may assign this
|
|
149
|
+
Agreement freely, including in connection with a merger, acquisition, or
|
|
150
|
+
sale of assets. This Agreement binds and benefits the parties' permitted
|
|
151
|
+
successors and assigns.
|
|
152
|
+
|
|
153
|
+
EXPORT COMPLIANCE. The SDK may be subject to export control laws,
|
|
154
|
+
including the U.S. Export Administration Regulations and applicable
|
|
155
|
+
sanctions programs. You represent that you are not located in, and will
|
|
156
|
+
not use or export the SDK in or to, any country or to any person or entity
|
|
157
|
+
subject to such restrictions, and that you will comply with all applicable
|
|
158
|
+
export and import laws.
|
|
159
|
+
|
|
160
|
+
U.S. GOVERNMENT END USERS. The SDK is "commercial computer software" and
|
|
161
|
+
"commercial computer software documentation" as those terms are used in
|
|
162
|
+
48 C.F.R. 12.212 and 48 C.F.R. 227.7202. Any use, duplication, or
|
|
163
|
+
disclosure by or on behalf of the U.S. Government is governed solely by
|
|
164
|
+
the terms of this Agreement.
|
|
165
|
+
|
|
166
|
+
For commercial licensing of Bitruvius encoder technology, or any questions
|
|
167
|
+
about this Agreement, contact: legal@bitruvius.com
|
package/README.md
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://bitruvius.com"><img src="https://cdn.bitruvius.com/brand/bitruvius-logo.png" width="360" alt="Bitruvius"></a>
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
# @bitruvius/geo-core
|
|
6
|
+
|
|
7
|
+
**The contracts and geospatial math every Bitruvius package shares, in pure TypeScript with no GPU, wasm or DOM.**
|
|
8
|
+
|
|
9
|
+
> **Internal building block.** This package exists so that
|
|
10
|
+
> [`@bitruvius/sdk-maplibre`](https://www.npmjs.com/package/@bitruvius/sdk-maplibre) and the
|
|
11
|
+
> Bitruvius codecs can resolve their dependencies on npm. It has no standalone product story.
|
|
12
|
+
> Unless you are deliberately building against it, install the SDK instead.
|
|
13
|
+
|
|
14
|
+
## Why it is a separate package
|
|
15
|
+
|
|
16
|
+
The SDK is assembled from packages that must not know about each other. A codec must not
|
|
17
|
+
depend on a streaming engine. An engine must not depend on a codec. A renderer must not
|
|
18
|
+
depend on a viewer. Each of those boundaries is an interface, and an interface has to live
|
|
19
|
+
somewhere both sides can import it from without importing each other. That is this package.
|
|
20
|
+
|
|
21
|
+
The seams are real, not theoretical:
|
|
22
|
+
|
|
23
|
+
- `@bitruvius/turbo-lepcc` and `@bitruvius/bvc` both implement `I3sPointCloudDecoder`.
|
|
24
|
+
The `@bitruvius/i3s` engine imports the interface and never a codec, so you swap LEPCC for
|
|
25
|
+
BVC without touching streaming or rendering.
|
|
26
|
+
- `@bitruvius/draco`, `@bitruvius/meshopt` and `@bitruvius/ktx2` implement
|
|
27
|
+
`DracoGeometryDecoder`, `MeshoptDecoder` and `Ktx2Transcoder`. They are injected into
|
|
28
|
+
`@bitruvius/gltf`, which is why a codec package depends on geo-core and never on the parser.
|
|
29
|
+
- The renderers (`splats`, `ptcloud`, `mesh`, `point-symbols`, `raster`) are driven entirely
|
|
30
|
+
through `ViewerAdapter` and `FrameState`. They do not know MapLibre exists. A new host is
|
|
31
|
+
one adapter file, not a renderer fork.
|
|
32
|
+
|
|
33
|
+
The second reason is purity. Nothing here touches WebGL, wasm or the DOM, so the same code
|
|
34
|
+
runs on the main thread, inside a decode worker, and under `bun test` with no browser. That
|
|
35
|
+
is a requirement, not a preference: the worker packs a tile into the shared ENU grid, the
|
|
36
|
+
shader expands it back, and the tests prove the two agree. Both sides have to be reading
|
|
37
|
+
the same arithmetic from the same file.
|
|
38
|
+
|
|
39
|
+
Twenty other packages in this repository depend on geo-core. It depends on one thing,
|
|
40
|
+
[`@bitruvius/foundation`](https://www.npmjs.com/package/@bitruvius/foundation).
|
|
41
|
+
|
|
42
|
+
## What is in it
|
|
43
|
+
|
|
44
|
+
**Contracts.** `Decoder` and `DecoderFactory`, `Renderer` and `TileHandle`, `ViewerAdapter`
|
|
45
|
+
and `FrameState`, plus the per-format decode seams: `GltfSplatDecoder`,
|
|
46
|
+
`I3sPointCloudDecoder`, `I3sMeshDecoder`, `CesiumPointDecoder`, `MeshTileDecoder`.
|
|
47
|
+
|
|
48
|
+
**The decoded model.** `DecodedSplatTile`, `DecodedPointTile` and `ContainerMeta` carry
|
|
49
|
+
quantized structure-of-arrays straight out of the decoder, because dequantization is
|
|
50
|
+
deferred to the render shaders. `PackedPointTile` and `PackedMeshTile` are the ENU-rebased,
|
|
51
|
+
GPU-ready forms the renderers upload. No floating-point geometry crosses this boundary.
|
|
52
|
+
|
|
53
|
+
**Geospatial math.** WGS84 geodetic to ECEF and back (Bowring closed form), ECEF to ENU,
|
|
54
|
+
and Web Mercator implemented from the public definition to match MapLibre's
|
|
55
|
+
`MercatorCoordinate` exactly, so this math is interchangeable with the viewer's own.
|
|
56
|
+
Column-major `mat4`/`mat3` and planes for frustum culling and clipping.
|
|
57
|
+
|
|
58
|
+
**Measurement.** What the SDK's measure tools are built on: slope and horizontal
|
|
59
|
+
distance, bearing, polyline length, polygon area and perimeter, the sampling grid behind
|
|
60
|
+
cut-and-fill volume, and contour extraction. These solve in the ENU tangent plane at the
|
|
61
|
+
feature being measured rather than on the ellipsoid, which is exact at city scale and
|
|
62
|
+
starts to drift past roughly 50 km; `haversineDistance` on the mean sphere is the
|
|
63
|
+
long-range cross-check and the axis measure for elevation profiles.
|
|
64
|
+
|
|
65
|
+
**Packing.** `packPointTileEnu`, `packI3sPointsEnu`, `packGltfPointsEnu` and `packMeshEnu`
|
|
66
|
+
rebase a decoded tile into the shared ENU meters frame and requantize it onto the
|
|
67
|
+
renderer's integer grid, so coordinates stay f32-exact however far the dataset sits from
|
|
68
|
+
the scene anchor. `extractHardEdges` derives the lines a person would draw if asked to
|
|
69
|
+
sketch a building, since no I3S or 3D Tiles service ships edge geometry.
|
|
70
|
+
|
|
71
|
+
**Placement.** `ModelPlacement` is the vocabulary the single-model layers expose: `upAxis`
|
|
72
|
+
preset, `heading`/`pitch`/`roll` in degrees, `scale`, `anchorPoint`. `placementBasis` and
|
|
73
|
+
`modelPlacementMatrix` compose the correct basis, including the mercator Y-flip that users
|
|
74
|
+
must never see. `QuantBoundsAccumulator` derives source-space bounds from streamed
|
|
75
|
+
quantized tiles, with robust percentiles, because splat captures arrive wrapped in a halo
|
|
76
|
+
of far-field background outliers that would otherwise hold the bounding box hostage.
|
|
77
|
+
|
|
78
|
+
**Style and metadata.** `compileSqlFilter` (Esri Building Scene Layer `filterExpression`)
|
|
79
|
+
and `compileStyleExpression` (3D Tiles declarative styling) compile to one AST and one
|
|
80
|
+
closure, evaluated per feature against a `PropertyGetter`. Hand-written tokenizer and
|
|
81
|
+
recursive-descent parser, no `eval`. I3S attributes, 3D Tiles batch tables and glTF
|
|
82
|
+
`EXT_structural_metadata` property tables all normalize into the same feature columns.
|
|
83
|
+
|
|
84
|
+
**Dequant reference.** The canonical inverse-quantization formulas. The GLSL shaders port
|
|
85
|
+
these functions, and this module is the parity oracle they are tested against.
|
|
86
|
+
|
|
87
|
+
Because geo-core re-exports `@bitruvius/foundation`, importing it also gives you the
|
|
88
|
+
domain-agnostic base: `TaskQueue`, `WorkerPool`, `detectCapabilities`,
|
|
89
|
+
`recommendDecodeBackend`, SDK config and `BitruviusError`.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { placementMatrix, toFloat32 } from '@bitruvius/geo-core';
|
|
93
|
+
|
|
94
|
+
const model = placementMatrix({ lng: -73.99, lat: 40.75, altitude: 0 });
|
|
95
|
+
gl.uniformMatrix4fv(uModel, false, toFloat32(model));
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Should you depend on it directly
|
|
99
|
+
|
|
100
|
+
Usually not. Install [`@bitruvius/sdk-maplibre`](https://www.npmjs.com/package/@bitruvius/sdk-maplibre)
|
|
101
|
+
and you get this package as a transitive dependency.
|
|
102
|
+
|
|
103
|
+
Depend on it directly when you are implementing one of its seams: a decoder for your own
|
|
104
|
+
container format that an SDK engine should stream, or a `ViewerAdapter` for a host the SDK
|
|
105
|
+
does not ship. Those are the cases where you want the interface and nothing else.
|
|
106
|
+
|
|
107
|
+
It is published for that purpose, not as a general-purpose geospatial math library. The API
|
|
108
|
+
tracks what the SDK needs and moves with SDK releases.
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
npm i @bitruvius/geo-core
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Trademarks
|
|
115
|
+
|
|
116
|
+
Esri, ArcGIS, I3S and LEPCC are trademarks of Environmental Systems Research Institute, Inc.
|
|
117
|
+
Cesium and 3D Tiles are trademarks of Cesium GS, Inc. Khronos, glTF and KTX are trademarks
|
|
118
|
+
of The Khronos Group Inc. Google and Draco are trademarks of Google LLC. Niantic and SPZ are
|
|
119
|
+
trademarks of Niantic, Inc. MapLibre is a trademark of the MapLibre organization. All other
|
|
120
|
+
marks are the property of their respective owners.
|
|
121
|
+
|
|
122
|
+
These names are used solely to describe the data formats this software interoperates with.
|
|
123
|
+
WebGL is a trademark of The Khronos Group Inc.
|
|
124
|
+
|
|
125
|
+
Bitruvius is not affiliated with, sponsored by, or endorsed by any of them, and no such
|
|
126
|
+
relationship is implied.
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
Proprietary. The full terms ship as `LICENSE` inside this package, and are readable
|
|
131
|
+
before installing at [cdn.bitruvius.com/legal/sdk-license-v1.txt](https://cdn.bitruvius.com/legal/sdk-license-v1.txt).
|
|
132
|
+
|
|
133
|
+
© Bitruvius, Inc.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `CesiumPointDecoder` — the loose-coupling seam for OGC 3D-Tiles **point cloud**
|
|
3
|
+
* (`.pnts` / glTF-1.1 POINTS) streaming, the Cesium analog of `I3sPointCloudDecoder`.
|
|
4
|
+
* It decodes one tile buffer into a GPU-ready, ENU-rebased `PackedPointTile`
|
|
5
|
+
* (the same shape the `@bitruvius/ptcloud` renderer already consumes), regardless
|
|
6
|
+
* of whether the geometry is uncompressed or Draco-compressed.
|
|
7
|
+
*
|
|
8
|
+
* The engine and the MapLibre layer depend ONLY on this interface — never on a
|
|
9
|
+
* concrete codec — so the uncompressed reader and the Draco-seam variant are
|
|
10
|
+
* interchangeable.
|
|
11
|
+
*/
|
|
12
|
+
import type { Mat4 } from '../geo/mat4';
|
|
13
|
+
import type { PackedPointTile } from '../geo/pack-point-enu';
|
|
14
|
+
export interface CesiumPointDecodeContext {
|
|
15
|
+
/** ECEF → shared-scene ENU (meters), column-major 4×4. */
|
|
16
|
+
readonly enuFromEcef: Mat4;
|
|
17
|
+
/** Cumulative tile transform: tile-local → ECEF. */
|
|
18
|
+
readonly tileTransformEcef: Mat4;
|
|
19
|
+
/** Requantization step (meters) for the i32 position grid. */
|
|
20
|
+
readonly grid: number;
|
|
21
|
+
}
|
|
22
|
+
/** Decodes one OGC 3D-Tiles point-cloud tile (`.pnts` / glTF-1.1 POINTS) into a
|
|
23
|
+
* GPU-ready, ENU-rebased `PackedPointTile`. */
|
|
24
|
+
export interface CesiumPointDecoder {
|
|
25
|
+
/** @param buffer - The tile bytes (`.pnts` or `.glb`).
|
|
26
|
+
* @param ctx - Georeference + requantize context (`CesiumPointDecodeContext`).
|
|
27
|
+
* @returns The ENU-rebased `PackedPointTile`. */
|
|
28
|
+
decode(buffer: ArrayBuffer, ctx: CesiumPointDecodeContext): Promise<PackedPointTile>;
|
|
29
|
+
/** Worker-pool size (worker variants) — size the engine's decode concurrency to match. */
|
|
30
|
+
readonly concurrency?: number;
|
|
31
|
+
dispose?(): void;
|
|
32
|
+
}
|
|
33
|
+
/** Built-in point-decoder identifiers a layer/engine can resolve to an impl. */
|
|
34
|
+
export type CesiumPointDecoderKind = 'pnts';
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decoder contract + the normalized decoded model.
|
|
3
|
+
*
|
|
4
|
+
* The model the SDK passes around is the **quantized** structure-of-
|
|
5
|
+
* arrays straight from the wasm decoder, plus the container metadata
|
|
6
|
+
* needed to dequantize. Dequant itself is deferred to the render
|
|
7
|
+
* shaders (upload compact bytes, expand on the GPU), so nothing here is
|
|
8
|
+
* floating-point geometry.
|
|
9
|
+
*/
|
|
10
|
+
import type { DecodeBackend } from '@bitruvius/foundation';
|
|
11
|
+
/** Which decoded model a container holds: a gaussian `splat` cloud or a `pointcloud`. */
|
|
12
|
+
export type ModelProfile = 'splat' | 'pointcloud';
|
|
13
|
+
/** Splat-container dequant metadata — the constants the render shader needs to expand
|
|
14
|
+
* the quantized {@link DecodedSplatTile} arrays back to meters/colors. */
|
|
15
|
+
export interface SplatContainerMeta {
|
|
16
|
+
/** Discriminant. */
|
|
17
|
+
readonly kind: 'splat';
|
|
18
|
+
/** Position grid divisor exponent: `meters = q / 2^fractionalBits`. */
|
|
19
|
+
readonly fractionalBits: number;
|
|
20
|
+
/** Container SH-degree hint (0..3). A per-tile degree may also be present. */
|
|
21
|
+
readonly shDegree: number;
|
|
22
|
+
}
|
|
23
|
+
/** Point-cloud-container dequant metadata: the per-axis affine that maps the quantized
|
|
24
|
+
* i32 grid back to world coordinates. */
|
|
25
|
+
export interface PointContainerMeta {
|
|
26
|
+
/** Discriminant. */
|
|
27
|
+
readonly kind: 'pointcloud';
|
|
28
|
+
/** Per-axis dequant scale (world = `q * scale + offset`). f64 — full precision. */
|
|
29
|
+
readonly scale: readonly [number, number, number];
|
|
30
|
+
/** Per-axis dequant offset (world = `q * scale + offset`). f64. */
|
|
31
|
+
readonly offset: readonly [number, number, number];
|
|
32
|
+
}
|
|
33
|
+
/** The container-level dequant metadata, discriminated by `kind`. */
|
|
34
|
+
export type ContainerMeta = SplatContainerMeta | PointContainerMeta;
|
|
35
|
+
/** One decoded gaussian-splat tile: quantized structure-of-arrays straight from the
|
|
36
|
+
* wasm decoder (dequant deferred to the render shader). All arrays have `count`
|
|
37
|
+
* elements unless noted; SH bands are present per `shDegree`. */
|
|
38
|
+
export interface DecodedSplatTile {
|
|
39
|
+
/** Discriminant. */
|
|
40
|
+
readonly kind: 'splat';
|
|
41
|
+
/** Splat count in this tile. */
|
|
42
|
+
readonly count: number;
|
|
43
|
+
/** Quantized position grid, X axis (`meters = q / 2^fractionalBits`). */
|
|
44
|
+
readonly x: Int32Array;
|
|
45
|
+
/** Quantized position grid, Y axis. */
|
|
46
|
+
readonly y: Int32Array;
|
|
47
|
+
/** Quantized position grid, Z axis. */
|
|
48
|
+
readonly z: Int32Array;
|
|
49
|
+
/** Opacity byte in the rendered (post-sigmoid) domain. */
|
|
50
|
+
readonly opacity: Uint8Array;
|
|
51
|
+
/** Log-quantized scale, X axis (see {@link splatScale}). */
|
|
52
|
+
readonly scaleX: Uint8Array;
|
|
53
|
+
/** Log-quantized scale, Y axis. */
|
|
54
|
+
readonly scaleY: Uint8Array;
|
|
55
|
+
/** Log-quantized scale, Z axis. */
|
|
56
|
+
readonly scaleZ: Uint8Array;
|
|
57
|
+
/** Smallest-three rotation: slot index of the omitted (largest `|component|`). */
|
|
58
|
+
readonly rotIdx: Uint8Array;
|
|
59
|
+
/** Smallest-three rotation component A (see {@link decodeSmallestThree}). */
|
|
60
|
+
readonly rotA: Int16Array;
|
|
61
|
+
/** Smallest-three rotation component B. */
|
|
62
|
+
readonly rotB: Int16Array;
|
|
63
|
+
/** Smallest-three rotation component C. */
|
|
64
|
+
readonly rotC: Int16Array;
|
|
65
|
+
/** SH degree-0 DC byte, red channel. */
|
|
66
|
+
readonly colorR: Uint8Array;
|
|
67
|
+
/** SH degree-0 DC byte, green channel. */
|
|
68
|
+
readonly colorG: Uint8Array;
|
|
69
|
+
/** SH degree-0 DC byte, blue channel. */
|
|
70
|
+
readonly colorB: Uint8Array;
|
|
71
|
+
/** This tile's SH degree (0..3). */
|
|
72
|
+
readonly shDegree: number;
|
|
73
|
+
/** Band-1 SH rest coefficients (`count*9` bytes); present when `shDegree >= 1`. */
|
|
74
|
+
readonly sh1?: Uint8Array;
|
|
75
|
+
/** Band-2 SH rest coefficients (`count*15` bytes); present when `shDegree >= 2`. */
|
|
76
|
+
readonly sh2?: Uint8Array;
|
|
77
|
+
/** Band-3 SH rest coefficients (`count*21` bytes); present when `shDegree === 3`. */
|
|
78
|
+
readonly sh3?: Uint8Array;
|
|
79
|
+
}
|
|
80
|
+
/** One decoded point-cloud tile: quantized i32 positions plus the present per-point
|
|
81
|
+
* attribute planes (all of length `count`). Dequant deferred to the render shader. */
|
|
82
|
+
export interface DecodedPointTile {
|
|
83
|
+
/** Discriminant. */
|
|
84
|
+
readonly kind: 'pointcloud';
|
|
85
|
+
/** Point count in this tile. */
|
|
86
|
+
readonly count: number;
|
|
87
|
+
/** Quantized position grid, X axis (`world = q * scale + offset`). */
|
|
88
|
+
readonly x: Int32Array;
|
|
89
|
+
/** Quantized position grid, Y axis. */
|
|
90
|
+
readonly y: Int32Array;
|
|
91
|
+
/** Quantized position grid, Z axis. */
|
|
92
|
+
readonly z: Int32Array;
|
|
93
|
+
/** Red channel (full-range u16), if colored. */
|
|
94
|
+
readonly r?: Uint16Array;
|
|
95
|
+
/** Green channel (full-range u16), if colored. */
|
|
96
|
+
readonly g?: Uint16Array;
|
|
97
|
+
/** Blue channel (full-range u16), if colored. */
|
|
98
|
+
readonly b?: Uint16Array;
|
|
99
|
+
/** LAS intensity (full-range u16), if present. */
|
|
100
|
+
readonly intensity?: Uint16Array;
|
|
101
|
+
/** LAS classification code, if present. */
|
|
102
|
+
readonly classification?: Uint8Array;
|
|
103
|
+
/** GPS time low 32 bits — reassemble as `lo + hi * 2^32`. */
|
|
104
|
+
readonly gpsLo?: Uint32Array;
|
|
105
|
+
/** GPS time high 32 bits. */
|
|
106
|
+
readonly gpsHi?: Uint32Array;
|
|
107
|
+
}
|
|
108
|
+
/** One decoded tile, discriminated by `kind`: a {@link DecodedSplatTile} or a
|
|
109
|
+
* {@link DecodedPointTile}. */
|
|
110
|
+
export type DecodedTile = DecodedSplatTile | DecodedPointTile;
|
|
111
|
+
/** Result of `Decoder.open` — the cheap header parse: which profile the
|
|
112
|
+
* container is, its dequant metadata, and how many tiles it holds. */
|
|
113
|
+
export interface DecodedModel {
|
|
114
|
+
/** `'splat'` or `'pointcloud'`. */
|
|
115
|
+
readonly profile: ModelProfile;
|
|
116
|
+
/** Container-level dequant metadata ({@link ContainerMeta}). */
|
|
117
|
+
readonly meta: ContainerMeta;
|
|
118
|
+
/** Number of tiles {@link Decoder.decodeTiles} will yield. */
|
|
119
|
+
readonly tileCount: number;
|
|
120
|
+
}
|
|
121
|
+
/** Options for {@link Decoder.decodeTiles}. */
|
|
122
|
+
export interface DecodeOptions {
|
|
123
|
+
/** Decode backend to use; omit to auto-select (see {@link recommendDecodeBackend}). */
|
|
124
|
+
readonly backend?: DecodeBackend;
|
|
125
|
+
/** Abort signal — aborting stops the stream and rejects in-flight work. */
|
|
126
|
+
readonly signal?: AbortSignal;
|
|
127
|
+
/** Streaming hook called as each tile finishes decoding.
|
|
128
|
+
* @param tile - The freshly decoded tile.
|
|
129
|
+
* @param index - Its 0-based index within the container. */
|
|
130
|
+
readonly onTile?: (tile: DecodedTile, index: number) => void;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The decode seam a codec satisfies and the streaming engines consume. Obtain one from
|
|
134
|
+
* a {@link DecoderFactory.create}; `open` the bytes to read the header, then
|
|
135
|
+
* `decodeTiles` to stream the quantized tiles.
|
|
136
|
+
*/
|
|
137
|
+
export interface Decoder {
|
|
138
|
+
/** The backend this decoder is actually running. */
|
|
139
|
+
readonly backend: DecodeBackend;
|
|
140
|
+
/**
|
|
141
|
+
* Parse the container header (cheap — no per-tile decode).
|
|
142
|
+
* @param bytes - The full container bytes.
|
|
143
|
+
* @returns The `DecodedModel` (profile + dequant meta + tile count).
|
|
144
|
+
* @throws BitruviusError `BVX_DECODE_FAILED` on bad magic / truncation / unsupported version.
|
|
145
|
+
*/
|
|
146
|
+
open(bytes: Uint8Array): Promise<DecodedModel>;
|
|
147
|
+
/**
|
|
148
|
+
* Stream-decode every tile. Each yielded tile's typed arrays are transferred from the
|
|
149
|
+
* worker (zero-copy), so do not reuse a tile's arrays after the next iteration.
|
|
150
|
+
* @param model - The `DecodedModel` from `open`.
|
|
151
|
+
* @param bytes - The full container bytes (same buffer passed to `open`).
|
|
152
|
+
* @param opts - Optional `DecodeOptions` (backend / abort / `onTile`).
|
|
153
|
+
* @returns An async iterable of `DecodedTile`s in container order.
|
|
154
|
+
* @throws BitruviusError `BVX_DECODE_FAILED` on a corrupt tile; `BVX_WORKER_SPAWN_BLOCKED`
|
|
155
|
+
* when a worker backend cannot start.
|
|
156
|
+
*/
|
|
157
|
+
decodeTiles(model: DecodedModel, bytes: Uint8Array, opts?: DecodeOptions): AsyncIterable<DecodedTile>;
|
|
158
|
+
/** Release the decoder's resources (worker pool, wasm instance). */
|
|
159
|
+
dispose(): void;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* The factory every codec package exports (one per format: `bvc`, `turbolzp`, …). The
|
|
163
|
+
* loose-coupling seam between a streaming engine and a concrete codec.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```ts
|
|
167
|
+
* const decoder = await factory.create({ poolSize: 4 });
|
|
168
|
+
* const model = await decoder.open(bytes);
|
|
169
|
+
* for await (const tile of decoder.decodeTiles(model, bytes)) {
|
|
170
|
+
* // upload `tile` to the GPU
|
|
171
|
+
* }
|
|
172
|
+
* decoder.dispose();
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export interface DecoderFactory {
|
|
176
|
+
/** Stable codec id (e.g. `'bvc'`). */
|
|
177
|
+
readonly id: string;
|
|
178
|
+
/** The backends this codec can run on this build. */
|
|
179
|
+
readonly supportedBackends: readonly DecodeBackend[];
|
|
180
|
+
/**
|
|
181
|
+
* Construct a {@link Decoder}.
|
|
182
|
+
* @param opts - Optional backend override and worker `poolSize`.
|
|
183
|
+
* @returns A ready {@link Decoder}.
|
|
184
|
+
* @throws BitruviusError `BVX_NO_BACKEND` when no requested/available backend is usable;
|
|
185
|
+
* `BVX_WASM_LOAD_FAILED` when the codec wasm cannot load.
|
|
186
|
+
*/
|
|
187
|
+
create(opts?: {
|
|
188
|
+
backend?: DecodeBackend;
|
|
189
|
+
poolSize?: number;
|
|
190
|
+
}): Promise<Decoder>;
|
|
191
|
+
}
|