@nika-js/onlymap 0.4.6 → 0.5.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/README.md +5 -4
- package/THIRD-PARTY-LICENSES.md +2 -2
- package/dist/{LercDecode.es-B49qauXg.js → LercDecode.es-B-OFS9hR.js} +1 -1
- package/dist/{basemap-nJ_ODY7r.js → basemap-CXVNH22A.js} +1 -1
- package/dist/cityjson-urQeujQv.js +407 -0
- package/dist/cityjson.d.ts +138 -0
- package/dist/data-layer.d.ts +10 -0
- package/dist/elements/om-map.d.ts +30 -0
- package/dist/{index-uDJbHjA9.js → index-BonJP_St.js} +1 -1
- package/dist/index-CW1n5LdO.js +4006 -0
- package/dist/{index-CeOjfL2p.js → index-CjZMcGou.js} +2 -2
- package/dist/{index-o_yRv2lD.js → index-DE7T4lfa.js} +1 -1
- package/dist/{index-DSkgI4Oc.js → index-DiYFebYs.js} +11142 -10971
- package/dist/{index-DjlGZov2.js → index-DuY3Zn6r.js} +1 -1
- package/dist/layer-registry.d.ts +14 -0
- package/dist/{lerc-CaQOmDCP.js → lerc-BhtFlCQ3.js} +2 -2
- package/dist/license.d.ts +34 -8
- package/dist/onlymap.standalone.js +22510 -21927
- package/dist/onlymapjs.js +19 -19
- package/dist/quota-notice.d.ts +43 -0
- package/dist/raster-BpVAEzbU.js +4842 -0
- package/dist/runtime-core.d.ts +1 -0
- package/dist/version.d.ts +1 -1
- package/docs/3d-assets.md +99 -1
- package/llms.txt +2 -2
- package/onlymapjs.html-data.json +12 -8
- package/package.json +2 -1
- package/skills/onlymapjs/SKILL.md +3 -1
- package/skills/onlymapjs/references/patterns.md +4 -0
- package/skills/onlymapjs/references/syntax.md +69 -16
- package/skills/onlymapjs/references/testing.md +1 -1
- package/dist/raster-DMq8FgiV.js +0 -8843
|
@@ -0,0 +1,4842 @@
|
|
|
1
|
+
import Ae from "./index-CW1n5LdO.js";
|
|
2
|
+
import { ak as Mt, al as Rt, am as tt, an as nt, ao as zt, b as Ft, ap as Dt, l as Ee, aq as Nt, d as Ut, ar as Bt, as as Gt, at as Kt, au as rt } from "./index-DiYFebYs.js";
|
|
3
|
+
import { w as _t } from "./mgrs-BY9bIvp4.js";
|
|
4
|
+
function Xt(e, t, n) {
|
|
5
|
+
const { projectedCorners: r } = t, { topLeft: o, topRight: i, bottomRight: s, bottomLeft: a } = r, l = n(o[0], o[1]), c = n(i[0], i[1]), u = n(s[0], s[1]), h = n(a[0], a[1]), p = [
|
|
6
|
+
l,
|
|
7
|
+
c,
|
|
8
|
+
u,
|
|
9
|
+
h,
|
|
10
|
+
l
|
|
11
|
+
], d = [
|
|
12
|
+
(l[0] + u[0]) / 2,
|
|
13
|
+
(l[1] + u[1]) / 2
|
|
14
|
+
], g = new Mt({
|
|
15
|
+
id: `${e}-label`,
|
|
16
|
+
data: [
|
|
17
|
+
{
|
|
18
|
+
position: d,
|
|
19
|
+
text: `x=${t.index.x} y=${t.index.y} z=${t.index.z}`
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
getColor: [255, 255, 255, 255],
|
|
23
|
+
getSize: 24,
|
|
24
|
+
sizeUnits: "pixels",
|
|
25
|
+
outlineWidth: 3,
|
|
26
|
+
outlineColor: [0, 0, 0, 255],
|
|
27
|
+
fontSettings: { sdf: !0 }
|
|
28
|
+
});
|
|
29
|
+
return [new Rt({
|
|
30
|
+
id: e,
|
|
31
|
+
data: [p],
|
|
32
|
+
getPath: (y) => y,
|
|
33
|
+
getColor: [255, 0, 0, 255],
|
|
34
|
+
// Red
|
|
35
|
+
getWidth: 2,
|
|
36
|
+
widthUnits: "pixels",
|
|
37
|
+
pickable: !1
|
|
38
|
+
}), g];
|
|
39
|
+
}
|
|
40
|
+
const Wt = [
|
|
41
|
+
[1 / 3, 1 / 3, 1 / 3],
|
|
42
|
+
// centroid
|
|
43
|
+
[0.5, 0.5, 0],
|
|
44
|
+
// edge 0–1
|
|
45
|
+
[0.5, 0, 0.5],
|
|
46
|
+
// edge 0–2
|
|
47
|
+
[0, 0.5, 0.5]
|
|
48
|
+
// edge 1–2
|
|
49
|
+
], Ht = 0.125;
|
|
50
|
+
class kt {
|
|
51
|
+
reprojectors;
|
|
52
|
+
/** Width of the image in pixels */
|
|
53
|
+
width;
|
|
54
|
+
/** Height of the image in pixels */
|
|
55
|
+
height;
|
|
56
|
+
/**
|
|
57
|
+
* UV vertex coordinates (x, y), i.e.
|
|
58
|
+
* [x0, y0, x1, y1, ...]
|
|
59
|
+
*
|
|
60
|
+
* These coordinates are floats that range from [0, 1] in both X and Y.
|
|
61
|
+
*/
|
|
62
|
+
uvs;
|
|
63
|
+
/**
|
|
64
|
+
* XY Positions in output CRS, computed via exact forward reprojection.
|
|
65
|
+
*/
|
|
66
|
+
exactOutputPositions;
|
|
67
|
+
/**
|
|
68
|
+
* triangle vertex indices
|
|
69
|
+
*/
|
|
70
|
+
triangles;
|
|
71
|
+
_halfedges;
|
|
72
|
+
/**
|
|
73
|
+
* The UV texture coordinates of candidates found from
|
|
74
|
+
* `findReprojectionCandidate`.
|
|
75
|
+
*
|
|
76
|
+
* Maybe in the future we'll want to store the barycentric coordinates instead
|
|
77
|
+
* of just the uv coordinates?
|
|
78
|
+
*/
|
|
79
|
+
_candidatesUV;
|
|
80
|
+
_queueIndices;
|
|
81
|
+
_queue;
|
|
82
|
+
_errors;
|
|
83
|
+
_pending;
|
|
84
|
+
_pendingLen;
|
|
85
|
+
constructor(t, n, r = n) {
|
|
86
|
+
this.reprojectors = t, this.width = n, this.height = r, this.uvs = [], this.exactOutputPositions = [], this.triangles = [], this._halfedges = [], this._candidatesUV = [], this._queueIndices = [], this._queue = [], this._errors = [], this._pending = [], this._pendingLen = 0;
|
|
87
|
+
const o = 1, i = 1, s = this._addPoint(0, 0), a = this._addPoint(o, 0), l = this._addPoint(0, i), c = this._addPoint(o, i), u = this._addTriangle(c, s, l, -1, -1, -1);
|
|
88
|
+
this._addTriangle(s, c, a, u, -1, -1), this._flush();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Refine the mesh until its maximum error gets below the given one
|
|
92
|
+
*
|
|
93
|
+
* @param maxError The maximum reprojection error in input pixels that the mesh should achieve.
|
|
94
|
+
* @param maxIterations Optional safeguard to prevent infinite loops in case of non-convergence. If the mesh fails to converge within this number of iterations, a warning will be logged and the function will return early.
|
|
95
|
+
*
|
|
96
|
+
* @return {[type]} [return description]
|
|
97
|
+
*/
|
|
98
|
+
run(t = Ht, { maxIterations: n = 1e4 } = {}) {
|
|
99
|
+
if (t <= 0)
|
|
100
|
+
throw new Error("maxError must be positive");
|
|
101
|
+
let r = 0;
|
|
102
|
+
for (; this.getMaxError() > t; )
|
|
103
|
+
if (this.refine(), ++r > n) {
|
|
104
|
+
console.warn(`RasterReprojector: mesh refinement did not converge after ${r} iterations (maxError=${t}, currentError=${this.getMaxError()})`);
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// refine the mesh with a single point
|
|
109
|
+
refine() {
|
|
110
|
+
this._step(), this._flush();
|
|
111
|
+
}
|
|
112
|
+
// max error of the current mesh
|
|
113
|
+
getMaxError() {
|
|
114
|
+
return this._errors[0];
|
|
115
|
+
}
|
|
116
|
+
// rasterize and queue all triangles that got added or updated in _step
|
|
117
|
+
_flush() {
|
|
118
|
+
for (let t = 0; t < this._pendingLen; t++) {
|
|
119
|
+
const n = this._pending[t];
|
|
120
|
+
this._findReprojectionCandidate(n);
|
|
121
|
+
}
|
|
122
|
+
this._pendingLen = 0;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Conversion of upstream's `_findCandidate` for reprojection error handling.
|
|
126
|
+
*
|
|
127
|
+
* @param t The index (into `this.triangles`) of the pending triangle to process.
|
|
128
|
+
*
|
|
129
|
+
* @return Doesn't return; instead modifies internal state.
|
|
130
|
+
*/
|
|
131
|
+
_findReprojectionCandidate(t) {
|
|
132
|
+
const n = 2 * this.triangles[t * 3 + 0], r = 2 * this.triangles[t * 3 + 1], o = 2 * this.triangles[t * 3 + 2], i = this.uvs[n], s = this.uvs[n + 1], a = this.uvs[r], l = this.uvs[r + 1], c = this.uvs[o], u = this.uvs[o + 1], h = this.exactOutputPositions[n], p = this.exactOutputPositions[n + 1], d = this.exactOutputPositions[r], g = this.exactOutputPositions[r + 1], f = this.exactOutputPositions[o], y = this.exactOutputPositions[o + 1];
|
|
133
|
+
let j = 0, b = 0, S = 0;
|
|
134
|
+
for (const v of Wt) {
|
|
135
|
+
const L = re(i, a, c, v[0], v[1], v[2]), E = re(s, l, u, v[0], v[1], v[2]), M = re(h, d, f, v[0], v[1], v[2]), z = re(p, g, y, v[0], v[1], v[2]), I = L * (this.width - 1), J = E * (this.height - 1), q = this.reprojectors.inverseReproject(M, z), te = this.reprojectors.inverseTransform(q[0], q[1]), ne = I - te[0], It = J - te[1], Oe = Math.hypot(ne, It);
|
|
136
|
+
Oe > j && (j = Oe, b = L, S = E);
|
|
137
|
+
}
|
|
138
|
+
(b === i && S === s || b === a && S === l || b === c && S === u) && (j = 0), this._candidatesUV[2 * t] = b, this._candidatesUV[2 * t + 1] = S, this._queuePush(t, j);
|
|
139
|
+
}
|
|
140
|
+
// process the next triangle in the queue, splitting it with a new point
|
|
141
|
+
_step() {
|
|
142
|
+
const t = this._queuePop(), n = t * 3 + 0, r = t * 3 + 1, o = t * 3 + 2, i = this.triangles[n], s = this.triangles[r], a = this.triangles[o], l = this.uvs[2 * i], c = this.uvs[2 * i + 1], u = this.uvs[2 * s], h = this.uvs[2 * s + 1], p = this.uvs[2 * a], d = this.uvs[2 * a + 1], g = this._candidatesUV[2 * t], f = this._candidatesUV[2 * t + 1], y = this._addPoint(g, f);
|
|
143
|
+
if (ce(l, c, u, h, g, f) === 0)
|
|
144
|
+
this._handleCollinear(y, n);
|
|
145
|
+
else if (ce(u, h, p, d, g, f) === 0)
|
|
146
|
+
this._handleCollinear(y, r);
|
|
147
|
+
else if (ce(p, d, l, c, g, f) === 0)
|
|
148
|
+
this._handleCollinear(y, o);
|
|
149
|
+
else {
|
|
150
|
+
const j = this._halfedges[n], b = this._halfedges[r], S = this._halfedges[o], v = this._addTriangle(i, s, y, j, -1, -1, n), L = this._addTriangle(s, a, y, b, -1, v + 1), E = this._addTriangle(a, i, y, S, v + 2, L + 1);
|
|
151
|
+
this._legalize(v), this._legalize(L), this._legalize(E);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// add coordinates for a new vertex
|
|
155
|
+
_addPoint(t, n) {
|
|
156
|
+
const r = this.uvs.length >> 1;
|
|
157
|
+
this.uvs.push(t, n);
|
|
158
|
+
const o = t * (this.width - 1), i = n * (this.height - 1), s = this.reprojectors.forwardTransform(o, i), a = this.reprojectors.forwardReproject(s[0], s[1]);
|
|
159
|
+
return this.exactOutputPositions.push(a[0], a[1]), r;
|
|
160
|
+
}
|
|
161
|
+
// add or update a triangle in the mesh
|
|
162
|
+
_addTriangle(t, n, r, o, i, s, a = this.triangles.length) {
|
|
163
|
+
const l = a / 3;
|
|
164
|
+
return this.triangles[a + 0] = t, this.triangles[a + 1] = n, this.triangles[a + 2] = r, this._halfedges[a + 0] = o, this._halfedges[a + 1] = i, this._halfedges[a + 2] = s, o >= 0 && (this._halfedges[o] = a + 0), i >= 0 && (this._halfedges[i] = a + 1), s >= 0 && (this._halfedges[s] = a + 2), this._candidatesUV[2 * l + 0] = 0, this._candidatesUV[2 * l + 1] = 0, this._queueIndices[l] = -1, this._pending[this._pendingLen++] = l, a;
|
|
165
|
+
}
|
|
166
|
+
_legalize(t) {
|
|
167
|
+
const n = this._halfedges[t];
|
|
168
|
+
if (n < 0)
|
|
169
|
+
return;
|
|
170
|
+
const r = t - t % 3, o = n - n % 3, i = r + (t + 1) % 3, s = r + (t + 2) % 3, a = o + (n + 2) % 3, l = o + (n + 1) % 3, c = this.triangles[s], u = this.triangles[t], h = this.triangles[i], p = this.triangles[a], d = this.uvs;
|
|
171
|
+
if (!Zt(d[2 * c], d[2 * c + 1], d[2 * u], d[2 * u + 1], d[2 * h], d[2 * h + 1], d[2 * p], d[2 * p + 1]))
|
|
172
|
+
return;
|
|
173
|
+
const g = this._halfedges[i], f = this._halfedges[s], y = this._halfedges[a], j = this._halfedges[l];
|
|
174
|
+
this._queueRemove(r / 3), this._queueRemove(o / 3);
|
|
175
|
+
const b = this._addTriangle(c, p, h, -1, y, g, r), S = this._addTriangle(p, c, u, b, f, j, o);
|
|
176
|
+
this._legalize(b + 1), this._legalize(S + 2);
|
|
177
|
+
}
|
|
178
|
+
// handle a case where new vertex is on the edge of a triangle
|
|
179
|
+
_handleCollinear(t, n) {
|
|
180
|
+
const r = n - n % 3, o = r + (n + 1) % 3, i = r + (n + 2) % 3, s = this.triangles[i], a = this.triangles[n], l = this.triangles[o], c = this._halfedges[o], u = this._halfedges[i], h = this._halfedges[n];
|
|
181
|
+
if (h < 0) {
|
|
182
|
+
const E = this._addTriangle(t, s, a, -1, u, -1, r), M = this._addTriangle(s, t, l, E, -1, c);
|
|
183
|
+
this._legalize(E + 1), this._legalize(M + 2);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const p = h - h % 3, d = p + (h + 2) % 3, g = p + (h + 1) % 3, f = this.triangles[d], y = this._halfedges[d], j = this._halfedges[g];
|
|
187
|
+
this._queueRemove(p / 3);
|
|
188
|
+
const b = this._addTriangle(s, a, t, u, -1, -1, r), S = this._addTriangle(a, f, t, j, -1, b + 1, p), v = this._addTriangle(f, l, t, y, -1, S + 1), L = this._addTriangle(l, s, t, c, b + 2, v + 1);
|
|
189
|
+
this._legalize(b), this._legalize(S), this._legalize(v), this._legalize(L);
|
|
190
|
+
}
|
|
191
|
+
// priority queue methods
|
|
192
|
+
_queuePush(t, n) {
|
|
193
|
+
const r = this._queue.length;
|
|
194
|
+
this._queueIndices[t] = r, this._queue.push(t), this._errors.push(n), this._queueUp(r);
|
|
195
|
+
}
|
|
196
|
+
_queuePop() {
|
|
197
|
+
const t = this._queue.length - 1;
|
|
198
|
+
return this._queueSwap(0, t), this._queueDown(0, t), this._queuePopBack();
|
|
199
|
+
}
|
|
200
|
+
_queuePopBack() {
|
|
201
|
+
const t = this._queue.pop();
|
|
202
|
+
return this._errors.pop(), this._queueIndices[t] = -1, t;
|
|
203
|
+
}
|
|
204
|
+
_queueRemove(t) {
|
|
205
|
+
const n = this._queueIndices[t];
|
|
206
|
+
if (n < 0) {
|
|
207
|
+
const o = this._pending.indexOf(t);
|
|
208
|
+
if (o !== -1)
|
|
209
|
+
this._pending[o] = this._pending[--this._pendingLen];
|
|
210
|
+
else
|
|
211
|
+
throw new Error("Broken triangulation (something went wrong).");
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const r = this._queue.length - 1;
|
|
215
|
+
r !== n && (this._queueSwap(n, r), this._queueDown(n, r) || this._queueUp(n)), this._queuePopBack();
|
|
216
|
+
}
|
|
217
|
+
_queueLess(t, n) {
|
|
218
|
+
return this._errors[t] > this._errors[n];
|
|
219
|
+
}
|
|
220
|
+
_queueSwap(t, n) {
|
|
221
|
+
const r = this._queue[t], o = this._queue[n];
|
|
222
|
+
this._queue[t] = o, this._queue[n] = r, this._queueIndices[r] = n, this._queueIndices[o] = t;
|
|
223
|
+
const i = this._errors[t];
|
|
224
|
+
this._errors[t] = this._errors[n], this._errors[n] = i;
|
|
225
|
+
}
|
|
226
|
+
_queueUp(t) {
|
|
227
|
+
let n = t;
|
|
228
|
+
for (; ; ) {
|
|
229
|
+
const r = n - 1 >> 1;
|
|
230
|
+
if (r === n || !this._queueLess(n, r))
|
|
231
|
+
break;
|
|
232
|
+
this._queueSwap(r, n), n = r;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
_queueDown(t, n) {
|
|
236
|
+
let r = t;
|
|
237
|
+
for (; ; ) {
|
|
238
|
+
const o = 2 * r + 1;
|
|
239
|
+
if (o >= n || o < 0)
|
|
240
|
+
break;
|
|
241
|
+
const i = o + 1;
|
|
242
|
+
let s = o;
|
|
243
|
+
if (i < n && this._queueLess(i, o) && (s = i), !this._queueLess(s, r))
|
|
244
|
+
break;
|
|
245
|
+
this._queueSwap(r, s), r = s;
|
|
246
|
+
}
|
|
247
|
+
return r > t;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function ce(e, t, n, r, o, i) {
|
|
251
|
+
return (n - o) * (t - i) - (r - i) * (e - o);
|
|
252
|
+
}
|
|
253
|
+
function Zt(e, t, n, r, o, i, s, a) {
|
|
254
|
+
const l = e - s, c = t - a, u = n - s, h = r - a, p = o - s, d = i - a, g = l * l + c * c, f = u * u + h * h, y = p * p + d * d;
|
|
255
|
+
return l * (h * y - f * d) - c * (u * y - f * p) + g * (u * d - h * p) < 0;
|
|
256
|
+
}
|
|
257
|
+
function re(e, t, n, r, o, i) {
|
|
258
|
+
return r * e + o * t + i * n;
|
|
259
|
+
}
|
|
260
|
+
const Se = {
|
|
261
|
+
name: "create-texture-unorm",
|
|
262
|
+
inject: {
|
|
263
|
+
"fs:#decl": "uniform sampler2D textureName;",
|
|
264
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
265
|
+
/* glsl */
|
|
266
|
+
`
|
|
267
|
+
color = texture(textureName, geometry.uv);
|
|
268
|
+
`
|
|
269
|
+
)
|
|
270
|
+
},
|
|
271
|
+
getUniforms: (e) => ({
|
|
272
|
+
textureName: e.textureName
|
|
273
|
+
})
|
|
274
|
+
}, Vt = (
|
|
275
|
+
/* glsl */
|
|
276
|
+
`#version 300 es
|
|
277
|
+
#define SHADER_NAME simple-mesh-layer-fs
|
|
278
|
+
|
|
279
|
+
precision highp float;
|
|
280
|
+
|
|
281
|
+
in vec2 vTexCoord;
|
|
282
|
+
in vec3 cameraPosition;
|
|
283
|
+
in vec3 normals_commonspace;
|
|
284
|
+
in vec4 position_commonspace;
|
|
285
|
+
in vec4 vColor;
|
|
286
|
+
|
|
287
|
+
out vec4 fragColor;
|
|
288
|
+
|
|
289
|
+
void main(void) {
|
|
290
|
+
geometry.uv = vTexCoord;
|
|
291
|
+
|
|
292
|
+
vec3 normal;
|
|
293
|
+
if (simpleMesh.flatShading) {
|
|
294
|
+
|
|
295
|
+
normal = normalize(cross(dFdx(position_commonspace.xyz), dFdy(position_commonspace.xyz)));
|
|
296
|
+
} else {
|
|
297
|
+
normal = normals_commonspace;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// We initialize color here before passing into DECKGL_FILTER_COLOR
|
|
301
|
+
vec4 color;
|
|
302
|
+
DECKGL_FILTER_COLOR(color, geometry);
|
|
303
|
+
|
|
304
|
+
vec3 lightColor = lighting_getLightColor(color.rgb, cameraPosition, position_commonspace.xyz, normal);
|
|
305
|
+
fragColor = vec4(lightColor, color.a * layer.opacity);
|
|
306
|
+
}
|
|
307
|
+
`
|
|
308
|
+
), Yt = {
|
|
309
|
+
...tt.defaultProps,
|
|
310
|
+
// Note: putting `image` in defaultProps causes Maplibre to fail to render
|
|
311
|
+
// labels in interleaved mode 🤷♂️
|
|
312
|
+
// image: { type: "image", value: null, async: true },
|
|
313
|
+
renderPipeline: { type: "array", value: [], compare: !0 },
|
|
314
|
+
// Disable lighting by default (avoids darkening raster)
|
|
315
|
+
material: {
|
|
316
|
+
ambient: 1,
|
|
317
|
+
diffuse: 0,
|
|
318
|
+
shininess: 0,
|
|
319
|
+
specularColor: [0, 0, 0]
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
class Jt extends tt {
|
|
323
|
+
static layerName = "mesh-texture-layer";
|
|
324
|
+
static defaultProps = Yt;
|
|
325
|
+
_resolveRenderPipeline() {
|
|
326
|
+
const { image: t, renderPipeline: n } = this.props;
|
|
327
|
+
return [...t ? [{ module: Se, props: { textureName: t } }] : [], ...n ?? []];
|
|
328
|
+
}
|
|
329
|
+
updateState(t) {
|
|
330
|
+
this.hasRenderPipelineChanged(t) && (t.changeFlags.extensionsChanged = !0), super.updateState(t);
|
|
331
|
+
}
|
|
332
|
+
/** Returns true if the render pipeline has changed between the old and new props. */
|
|
333
|
+
hasRenderPipelineChanged(t) {
|
|
334
|
+
const { oldProps: n, props: r } = t;
|
|
335
|
+
if (!!n.image != !!r.image)
|
|
336
|
+
return !0;
|
|
337
|
+
const o = n.renderPipeline ?? [], i = r.renderPipeline ?? [];
|
|
338
|
+
if (o.length !== i.length)
|
|
339
|
+
return !0;
|
|
340
|
+
for (let s = 0; s < o.length; s++)
|
|
341
|
+
if (o[s]?.module.name !== i[s]?.module.name)
|
|
342
|
+
return !0;
|
|
343
|
+
return !1;
|
|
344
|
+
}
|
|
345
|
+
getShaders() {
|
|
346
|
+
const t = super.getShaders(), n = t.modules;
|
|
347
|
+
for (const r of this._resolveRenderPipeline())
|
|
348
|
+
n.push(r.module);
|
|
349
|
+
return {
|
|
350
|
+
...t,
|
|
351
|
+
// Override upstream's fragment shader with our copy with modified
|
|
352
|
+
// injection points
|
|
353
|
+
fs: Vt,
|
|
354
|
+
modules: n
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
draw(t) {
|
|
358
|
+
const n = {};
|
|
359
|
+
for (const r of this._resolveRenderPipeline())
|
|
360
|
+
n[r.module.name] = r.props || {};
|
|
361
|
+
for (const r of super.getModels())
|
|
362
|
+
r.shaderInputs.setProps(n);
|
|
363
|
+
super.draw(t);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const qt = 0.125, Ie = [
|
|
367
|
+
[252, 73, 163],
|
|
368
|
+
// pink
|
|
369
|
+
[255, 51, 204],
|
|
370
|
+
// magenta-pink
|
|
371
|
+
[204, 102, 255],
|
|
372
|
+
// purple-ish
|
|
373
|
+
[153, 51, 255],
|
|
374
|
+
// deep purple
|
|
375
|
+
[102, 204, 255],
|
|
376
|
+
// sky blue
|
|
377
|
+
[51, 153, 255],
|
|
378
|
+
// clear blue
|
|
379
|
+
[102, 255, 204],
|
|
380
|
+
// teal
|
|
381
|
+
[51, 255, 170],
|
|
382
|
+
// aqua-teal
|
|
383
|
+
[0, 255, 0],
|
|
384
|
+
// lime green
|
|
385
|
+
[51, 204, 51],
|
|
386
|
+
// stronger green
|
|
387
|
+
[255, 204, 102],
|
|
388
|
+
// light orange
|
|
389
|
+
[255, 179, 71],
|
|
390
|
+
// golden-orange
|
|
391
|
+
[255, 102, 102],
|
|
392
|
+
// salmon
|
|
393
|
+
[255, 80, 80],
|
|
394
|
+
// red-salmon
|
|
395
|
+
[255, 0, 0],
|
|
396
|
+
// red
|
|
397
|
+
[204, 0, 0],
|
|
398
|
+
// crimson
|
|
399
|
+
[255, 128, 0],
|
|
400
|
+
// orange
|
|
401
|
+
[255, 153, 51],
|
|
402
|
+
// bright orange
|
|
403
|
+
[255, 255, 102],
|
|
404
|
+
// yellow
|
|
405
|
+
[255, 255, 51],
|
|
406
|
+
// lemon
|
|
407
|
+
[0, 255, 255],
|
|
408
|
+
// turquoise
|
|
409
|
+
[0, 204, 255]
|
|
410
|
+
// cyan
|
|
411
|
+
], Qt = {
|
|
412
|
+
// A prop with `type: "image"` gets converted to a texture automatically by
|
|
413
|
+
// deck.gl (as long as async: true)
|
|
414
|
+
image: { type: "image", value: null, async: !0 },
|
|
415
|
+
renderPipeline: { type: "array", value: [], compare: !0 },
|
|
416
|
+
debug: !1,
|
|
417
|
+
debugOpacity: 0.5
|
|
418
|
+
};
|
|
419
|
+
class Tt extends nt {
|
|
420
|
+
static layerName = "RasterLayer";
|
|
421
|
+
static defaultProps = Qt;
|
|
422
|
+
initializeState() {
|
|
423
|
+
this.setState({});
|
|
424
|
+
}
|
|
425
|
+
updateState(t) {
|
|
426
|
+
super.updateState(t);
|
|
427
|
+
const { props: n, oldProps: r, changeFlags: o } = t, i = n.reprojectionFns.forwardTransform !== r.reprojectionFns?.forwardTransform || n.reprojectionFns.inverseTransform !== r.reprojectionFns?.inverseTransform || n.reprojectionFns.forwardReproject !== r.reprojectionFns?.forwardReproject || n.reprojectionFns.inverseReproject !== r.reprojectionFns?.inverseReproject;
|
|
428
|
+
(!!o.dataChanged || n.width !== r.width || n.height !== r.height || i || n.maxError !== r.maxError) && this._generateMesh();
|
|
429
|
+
}
|
|
430
|
+
_generateMesh() {
|
|
431
|
+
const { width: t, height: n, reprojectionFns: r, maxError: o = qt } = this.props, i = new kt(r, t + 1, n + 1);
|
|
432
|
+
i.run(o);
|
|
433
|
+
const { indices: s, positions: a, texCoords: l } = $t(i);
|
|
434
|
+
this.setState({
|
|
435
|
+
reprojector: i,
|
|
436
|
+
mesh: {
|
|
437
|
+
indices: { value: s, size: 1 },
|
|
438
|
+
attributes: {
|
|
439
|
+
POSITION: { value: a, size: 3 },
|
|
440
|
+
TEXCOORD_0: { value: l, size: 2 }
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
renderDebugLayer() {
|
|
446
|
+
const { reprojector: t } = this.state, { debugOpacity: n } = this.props;
|
|
447
|
+
return t ? new zt(this.getSubLayerProps({
|
|
448
|
+
id: "polygon",
|
|
449
|
+
// https://deck.gl/docs/developer-guide/performance#supply-binary-blobs-to-the-data-prop
|
|
450
|
+
// This `data` gets passed into `getPolygon` with the row index.
|
|
451
|
+
data: { reprojector: t, length: t.triangles.length / 3 },
|
|
452
|
+
getPolygon: (r, { index: o, data: i }) => {
|
|
453
|
+
const s = i.reprojector.triangles, a = t.exactOutputPositions, l = s[o * 3], c = s[o * 3 + 1], u = s[o * 3 + 2];
|
|
454
|
+
return [
|
|
455
|
+
[a[l * 2], a[l * 2 + 1]],
|
|
456
|
+
[a[c * 2], a[c * 2 + 1]],
|
|
457
|
+
[a[u * 2], a[u * 2 + 1]],
|
|
458
|
+
[a[l * 2], a[l * 2 + 1]]
|
|
459
|
+
];
|
|
460
|
+
},
|
|
461
|
+
getFillColor: (r, { index: o, target: i }) => {
|
|
462
|
+
const s = Ie[o % Ie.length];
|
|
463
|
+
return i[0] = s[0], i[1] = s[1], i[2] = s[2], i[3] = 255, i;
|
|
464
|
+
},
|
|
465
|
+
getLineColor: [0, 0, 0],
|
|
466
|
+
getLineWidth: 1,
|
|
467
|
+
lineWidthUnits: "pixels",
|
|
468
|
+
opacity: n !== void 0 && Number.isFinite(n) ? Math.max(0, Math.min(1, n)) : 1,
|
|
469
|
+
pickable: !1
|
|
470
|
+
})) : null;
|
|
471
|
+
}
|
|
472
|
+
renderLayers() {
|
|
473
|
+
const { mesh: t } = this.state, { debug: n, image: r, renderPipeline: o } = this.props;
|
|
474
|
+
if (!t || !r && (o?.length ?? 0) === 0)
|
|
475
|
+
return null;
|
|
476
|
+
const s = [new Jt(this.getSubLayerProps({
|
|
477
|
+
id: "raster",
|
|
478
|
+
image: r,
|
|
479
|
+
renderPipeline: o,
|
|
480
|
+
// Dummy data because we're only rendering _one_ instance of this mesh
|
|
481
|
+
// https://github.com/visgl/deck.gl/blob/93111b667b919148da06ff1918410cf66381904f/modules/geo-layers/src/terrain-layer/terrain-layer.ts#L241
|
|
482
|
+
data: [1],
|
|
483
|
+
mesh: t,
|
|
484
|
+
// We're only rendering a single mesh, without instancing
|
|
485
|
+
// https://github.com/visgl/deck.gl/blob/93111b667b919148da06ff1918410cf66381904f/modules/geo-layers/src/terrain-layer/terrain-layer.ts#L244
|
|
486
|
+
_instanced: !1,
|
|
487
|
+
// Dummy accessors for the dummy data
|
|
488
|
+
// We place our mesh at the coordinate origin
|
|
489
|
+
getPosition: [0, 0, 0],
|
|
490
|
+
// We give a white color to turn off color mixing with the texture
|
|
491
|
+
getColor: [255, 255, 255]
|
|
492
|
+
}))];
|
|
493
|
+
if (n) {
|
|
494
|
+
const a = this.renderDebugLayer();
|
|
495
|
+
a && s.push(a);
|
|
496
|
+
}
|
|
497
|
+
return s;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
function $t(e) {
|
|
501
|
+
const t = e.uvs.length / 2, n = new Float32Array(t * 3), r = new Float32Array(e.uvs);
|
|
502
|
+
for (let i = 0; i < t; i++)
|
|
503
|
+
n[i * 3] = e.exactOutputPositions[i * 2], n[i * 3 + 1] = e.exactOutputPositions[i * 2 + 1], n[i * 3 + 2] = 0;
|
|
504
|
+
return {
|
|
505
|
+
indices: new Uint32Array(e.triangles),
|
|
506
|
+
positions: n,
|
|
507
|
+
texCoords: r
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
class en {
|
|
511
|
+
levels;
|
|
512
|
+
projectTo3857;
|
|
513
|
+
projectFrom3857;
|
|
514
|
+
projectTo4326;
|
|
515
|
+
projectFrom4326;
|
|
516
|
+
projectedBounds;
|
|
517
|
+
constructor(t) {
|
|
518
|
+
if (t.levels.length === 0)
|
|
519
|
+
throw new Error("AffineTileset requires at least one level");
|
|
520
|
+
this.levels = t.levels, this.projectTo3857 = t.projectTo3857, this.projectFrom3857 = t.projectFrom3857, this.projectTo4326 = t.projectTo4326, this.projectFrom4326 = t.projectFrom4326, this.projectedBounds = t.levels[0].projectedBounds;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
function Le(e, t) {
|
|
524
|
+
return [1, 0, e, 0, 1, t];
|
|
525
|
+
}
|
|
526
|
+
function tn(e, t = e) {
|
|
527
|
+
return [e, 0, 0, 0, t, 0];
|
|
528
|
+
}
|
|
529
|
+
function A([e, t, n, r, o, i], s, a) {
|
|
530
|
+
return [
|
|
531
|
+
e * s + t * a + n,
|
|
532
|
+
r * s + o * a + i
|
|
533
|
+
];
|
|
534
|
+
}
|
|
535
|
+
function ae([e, t, n, r, o, i], [s, a, l, c, u, h]) {
|
|
536
|
+
return [
|
|
537
|
+
e * s + t * c,
|
|
538
|
+
e * a + t * u,
|
|
539
|
+
e * l + t * h + n,
|
|
540
|
+
r * s + o * c,
|
|
541
|
+
r * a + o * u,
|
|
542
|
+
r * l + o * h + i
|
|
543
|
+
];
|
|
544
|
+
}
|
|
545
|
+
function de([e, t, n, r, o, i]) {
|
|
546
|
+
const s = e * o - t * r;
|
|
547
|
+
if (s === 0)
|
|
548
|
+
throw new Error("Cannot invert degenerate transform");
|
|
549
|
+
const a = 1 / s, l = o * a, c = -t * a, u = -r * a, h = e * a;
|
|
550
|
+
return [
|
|
551
|
+
l,
|
|
552
|
+
c,
|
|
553
|
+
-n * l - i * c,
|
|
554
|
+
u,
|
|
555
|
+
h,
|
|
556
|
+
-n * u - i * h
|
|
557
|
+
];
|
|
558
|
+
}
|
|
559
|
+
function nn(e) {
|
|
560
|
+
return e[0];
|
|
561
|
+
}
|
|
562
|
+
function rn(e) {
|
|
563
|
+
return e[4];
|
|
564
|
+
}
|
|
565
|
+
class on {
|
|
566
|
+
tileWidth;
|
|
567
|
+
tileHeight;
|
|
568
|
+
matrixWidth;
|
|
569
|
+
matrixHeight;
|
|
570
|
+
metersPerPixel;
|
|
571
|
+
/**
|
|
572
|
+
* Source-CRS bounding box of the level's array `[minX, minY, maxX, maxY]`.
|
|
573
|
+
* Computed from the affine applied to the four array corners.
|
|
574
|
+
*/
|
|
575
|
+
projectedBounds;
|
|
576
|
+
_affine;
|
|
577
|
+
_invAffine;
|
|
578
|
+
constructor(t) {
|
|
579
|
+
this._affine = t.affine, this._invAffine = de(t.affine), this.tileWidth = t.tileWidth, this.tileHeight = t.tileHeight, this.matrixWidth = Math.ceil(t.arrayWidth / t.tileWidth), this.matrixHeight = Math.ceil(t.arrayHeight / t.tileHeight);
|
|
580
|
+
const n = nn(t.affine), r = rn(t.affine);
|
|
581
|
+
this.metersPerPixel = Math.sqrt(Math.abs(n * r)) * t.mpu;
|
|
582
|
+
const o = [
|
|
583
|
+
A(t.affine, 0, 0),
|
|
584
|
+
A(t.affine, t.arrayWidth, 0),
|
|
585
|
+
A(t.affine, 0, t.arrayHeight),
|
|
586
|
+
A(t.affine, t.arrayWidth, t.arrayHeight)
|
|
587
|
+
], i = o.map(([a]) => a), s = o.map(([, a]) => a);
|
|
588
|
+
this.projectedBounds = [
|
|
589
|
+
Math.min(...i),
|
|
590
|
+
Math.min(...s),
|
|
591
|
+
Math.max(...i),
|
|
592
|
+
Math.max(...s)
|
|
593
|
+
];
|
|
594
|
+
}
|
|
595
|
+
projectedTileCorners(t, n) {
|
|
596
|
+
const r = this.tileWidth, o = this.tileHeight, i = this._affine;
|
|
597
|
+
return {
|
|
598
|
+
topLeft: A(i, t * r, n * o),
|
|
599
|
+
topRight: A(i, (t + 1) * r, n * o),
|
|
600
|
+
bottomLeft: A(i, t * r, (n + 1) * o),
|
|
601
|
+
bottomRight: A(i, (t + 1) * r, (n + 1) * o)
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
tileTransform(t, n) {
|
|
605
|
+
const r = Le(t * this.tileWidth, n * this.tileHeight), o = ae(this._affine, r), i = de(o);
|
|
606
|
+
return {
|
|
607
|
+
forwardTransform: (s, a) => A(o, s, a),
|
|
608
|
+
inverseTransform: (s, a) => A(i, s, a)
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
crsBoundsToTileRange(t, n, r, o) {
|
|
612
|
+
const i = this._invAffine, s = [
|
|
613
|
+
A(i, t, n),
|
|
614
|
+
A(i, r, n),
|
|
615
|
+
A(i, t, o),
|
|
616
|
+
A(i, r, o)
|
|
617
|
+
], a = s.map(([L]) => L), l = s.map(([, L]) => L), c = Math.min(...a), u = Math.max(...a), h = Math.min(...l), p = Math.max(...l), d = this.tileWidth, g = this.tileHeight, f = this.matrixWidth - 1, y = this.matrixHeight - 1, j = Math.max(0, Math.floor(c / d)), b = Math.min(f, Math.floor(u / d)), S = Math.max(0, Math.floor(h / g)), v = Math.min(y, Math.floor(p / g));
|
|
618
|
+
return { minCol: j, maxCol: b, minRow: S, maxRow: v };
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
function sn(e, { semiMajorAxis: t } = {}) {
|
|
622
|
+
switch (e = e.toLowerCase(), e) {
|
|
623
|
+
case "m":
|
|
624
|
+
case "metre":
|
|
625
|
+
case "meter":
|
|
626
|
+
case "meters":
|
|
627
|
+
return 1;
|
|
628
|
+
case "foot":
|
|
629
|
+
return 0.3048;
|
|
630
|
+
case "us survey foot":
|
|
631
|
+
return 1200 / 3937;
|
|
632
|
+
}
|
|
633
|
+
if (e === "degree") {
|
|
634
|
+
if (t === void 0)
|
|
635
|
+
throw new Error("CRS with degrees unit requires ellipsoid semi-major-axis");
|
|
636
|
+
return 2 * Math.PI * t / 360;
|
|
637
|
+
}
|
|
638
|
+
throw new Error(`Unsupported CRS units: ${e} when computing metersPerUnit.`);
|
|
639
|
+
}
|
|
640
|
+
function ot(e) {
|
|
641
|
+
const t = _t(e);
|
|
642
|
+
return t.projName === "longlat" && (!t.units || t.units === "unknown") && (t.units = "degree", t.to_meter = void 0), t;
|
|
643
|
+
}
|
|
644
|
+
const Me = /* @__PURE__ */ new Map();
|
|
645
|
+
async function an(e) {
|
|
646
|
+
const t = `EPSG:${e}`, n = Me.get(t);
|
|
647
|
+
if (n !== void 0)
|
|
648
|
+
return n;
|
|
649
|
+
const r = await ln(e), o = ot(r);
|
|
650
|
+
return Me.set(t, o), o;
|
|
651
|
+
}
|
|
652
|
+
async function ln(e) {
|
|
653
|
+
const t = `https://epsg.io/${e}.json`, n = await fetch(t);
|
|
654
|
+
if (!n.ok)
|
|
655
|
+
throw new Error(`Failed to fetch PROJJSON from ${t}`);
|
|
656
|
+
return await n.json();
|
|
657
|
+
}
|
|
658
|
+
function pe(e, t, n, r, o, i = {}) {
|
|
659
|
+
const { densifyPts: s = 21 } = i, a = [t, r, r, t], l = [n, n, o, o];
|
|
660
|
+
let c = 1 / 0, u = 1 / 0, h = -1 / 0, p = -1 / 0;
|
|
661
|
+
for (let d = 0; d < 4; d++) {
|
|
662
|
+
const g = a[d], f = l[d], y = a[(d + 1) % 4], j = l[(d + 1) % 4];
|
|
663
|
+
for (let b = 0; b <= s; b++) {
|
|
664
|
+
const S = b / (s + 1), [v, L] = e(g + (y - g) * S, f + (j - f) * S);
|
|
665
|
+
v < c && (c = v), L < u && (u = L), v > h && (h = v), L > p && (p = L);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
return [c, u, h, p];
|
|
669
|
+
}
|
|
670
|
+
const Re = 6378137, ze = 85.05112877980659;
|
|
671
|
+
function cn(e, t) {
|
|
672
|
+
const n = e * Math.PI * Re / 180, r = t * Math.PI / 180, o = Math.log(Math.tan(Math.PI / 4 + r / 2)) * Re;
|
|
673
|
+
return [n, o];
|
|
674
|
+
}
|
|
675
|
+
function un(e, t) {
|
|
676
|
+
return (n, r) => {
|
|
677
|
+
const [o, i] = e(n, r);
|
|
678
|
+
if (Number.isFinite(o) && Number.isFinite(i))
|
|
679
|
+
return [o, i];
|
|
680
|
+
const [s, a] = t(n, r), l = Math.max(-ze, Math.min(ze, a));
|
|
681
|
+
return cn(s, l);
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
const hn = 65536;
|
|
685
|
+
class it {
|
|
686
|
+
entries = /* @__PURE__ */ new Map();
|
|
687
|
+
maxEntries;
|
|
688
|
+
constructor({ maxEntries: t = hn } = {}) {
|
|
689
|
+
this.maxEntries = Math.max(0, t);
|
|
690
|
+
}
|
|
691
|
+
/** Number of cached entries. */
|
|
692
|
+
get size() {
|
|
693
|
+
return this.entries.size;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Look up the cached bounding volume for tile `(z, x, y)`. On a hit the entry
|
|
697
|
+
* is marked most-recently-used. Returns `undefined` on a miss.
|
|
698
|
+
*/
|
|
699
|
+
get(t, n, r) {
|
|
700
|
+
const o = `${t}/${n}/${r}`, i = this.entries.get(o);
|
|
701
|
+
if (i !== void 0)
|
|
702
|
+
return this.entries.delete(o), this.entries.set(o, i), i;
|
|
703
|
+
}
|
|
704
|
+
/** Store the bounding volume for tile `(z, x, y)` as most-recently-used. */
|
|
705
|
+
set(t, n, r, o) {
|
|
706
|
+
const i = `${t}/${n}/${r}`;
|
|
707
|
+
this.entries.delete(i), this.entries.set(i, o);
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* If the cache is over its soft cap, drop least-recently-used entries down to
|
|
711
|
+
* roughly half of `maxEntries`. No-op when at or under the cap. Call once at
|
|
712
|
+
* the start of a traversal, never mid-traversal.
|
|
713
|
+
*/
|
|
714
|
+
sweep() {
|
|
715
|
+
if (this.entries.size <= this.maxEntries)
|
|
716
|
+
return;
|
|
717
|
+
const t = Math.floor(this.maxEntries / 2), n = this.entries.size - t, r = [];
|
|
718
|
+
for (const o of this.entries.keys())
|
|
719
|
+
if (r.push(o), r.length >= n)
|
|
720
|
+
break;
|
|
721
|
+
for (const o of r)
|
|
722
|
+
this.entries.delete(o);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
const Fe = 512, dn = [
|
|
726
|
+
[0.5, 0.5],
|
|
727
|
+
// center
|
|
728
|
+
[0, 0],
|
|
729
|
+
// top-left
|
|
730
|
+
[0, 1],
|
|
731
|
+
// bottom-left
|
|
732
|
+
[1, 0],
|
|
733
|
+
// top-right
|
|
734
|
+
[1, 1]
|
|
735
|
+
// bottom-right
|
|
736
|
+
], pn = dn.concat([
|
|
737
|
+
[0, 0.5],
|
|
738
|
+
// left edge
|
|
739
|
+
[0.5, 0],
|
|
740
|
+
// top edge
|
|
741
|
+
[1, 0.5],
|
|
742
|
+
// right edge
|
|
743
|
+
[0.5, 1]
|
|
744
|
+
// bottom edge
|
|
745
|
+
]), me = 6378137, ge = 2 * Math.PI * me, De = ge / 2, Ne = 85.05112877980659;
|
|
746
|
+
class ie {
|
|
747
|
+
/** Index across a row */
|
|
748
|
+
x;
|
|
749
|
+
/** Index down a column */
|
|
750
|
+
y;
|
|
751
|
+
/** Zoom index assumed to be (higher = finer detail) */
|
|
752
|
+
z;
|
|
753
|
+
descriptor;
|
|
754
|
+
/**
|
|
755
|
+
* Flag indicating whether any descendant of this tile is visible.
|
|
756
|
+
*
|
|
757
|
+
* Used to prevent loading parent tiles when children are visible (avoids
|
|
758
|
+
* overdraw).
|
|
759
|
+
*/
|
|
760
|
+
childVisible;
|
|
761
|
+
/**
|
|
762
|
+
* Flag indicating this tile should be rendered
|
|
763
|
+
*
|
|
764
|
+
* Set to `true` when this is the appropriate LOD for its distance from camera.
|
|
765
|
+
*/
|
|
766
|
+
selected;
|
|
767
|
+
/** A cache of the children of this node. */
|
|
768
|
+
_children;
|
|
769
|
+
constructor(t, n, r, { descriptor: o }) {
|
|
770
|
+
this.x = t, this.y = n, this.z = r, this.descriptor = o;
|
|
771
|
+
}
|
|
772
|
+
/** Get the level info for this tile's z index. */
|
|
773
|
+
get level() {
|
|
774
|
+
return this.descriptor.levels[this.z];
|
|
775
|
+
}
|
|
776
|
+
/** Get the children of this node.
|
|
777
|
+
*
|
|
778
|
+
* Find all tiles at level this.z + 1 whose spatial extent overlaps this tile.
|
|
779
|
+
*
|
|
780
|
+
* A tileset pyramid is not guaranteed to be a quadtree — it is a stack of
|
|
781
|
+
* independent grids. We find children by mapping the parent tile's CRS bounds
|
|
782
|
+
* into the child grid using {@link RasterTilesetLevel.crsBoundsToTileRange}.
|
|
783
|
+
*/
|
|
784
|
+
get children() {
|
|
785
|
+
if (!this._children) {
|
|
786
|
+
const t = this.descriptor.levels.length - 1;
|
|
787
|
+
if (this.z >= t)
|
|
788
|
+
return this._children = null, null;
|
|
789
|
+
const n = this.z + 1, r = this.descriptor.levels[n], o = this.level.projectedTileCorners(this.x, this.y), i = Sn(o), { minCol: s, maxCol: a, minRow: l, maxRow: c } = r.crsBoundsToTileRange(...i), u = [], { descriptor: h } = this;
|
|
790
|
+
for (let p = l; p <= c; p++)
|
|
791
|
+
for (let d = s; d <= a; d++)
|
|
792
|
+
u.push(new ie(d, p, n, { descriptor: h }));
|
|
793
|
+
this._children = u.length > 0 ? u : null;
|
|
794
|
+
}
|
|
795
|
+
return this._children;
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Recursively traverse the tile pyramid to determine if this tile (or its
|
|
799
|
+
* descendants) should be rendered.
|
|
800
|
+
*
|
|
801
|
+
* I.e. "Given this tile node, should I render this tile, or should I recurse
|
|
802
|
+
* into its children?"
|
|
803
|
+
*
|
|
804
|
+
* The algorithm performs:
|
|
805
|
+
* 1. Visibility culling - reject tiles outside the view frustum
|
|
806
|
+
* 2. Bounds checking - reject tiles outside the specified geographic bounds
|
|
807
|
+
* 3. LOD selection - choose appropriate zoom level based on distance from camera
|
|
808
|
+
* 4. Recursive subdivision - if LOD is insufficient, test child tiles
|
|
809
|
+
*
|
|
810
|
+
* Additionally, there should never be overdraw, i.e. a tile should never be
|
|
811
|
+
* rendered if any of its descendants are rendered.
|
|
812
|
+
*
|
|
813
|
+
* @returns true if this tile or any descendant is visible, false otherwise
|
|
814
|
+
*/
|
|
815
|
+
update(t) {
|
|
816
|
+
this.childVisible = !1, this.selected = !1;
|
|
817
|
+
const { viewport: n, cullingVolume: r, elevationBounds: o, minZ: i, maxZ: s = this.descriptor.levels.length - 1, project: a, bounds: l, pixelRatio: c, boundingVolumeCache: u } = t, { boundingVolume: h, commonSpaceBounds: p } = this.getBoundingVolume(o, a, u);
|
|
818
|
+
if (l && !this.insideBounds(l, p) || r.computeVisibility(h) < 0)
|
|
819
|
+
return !1;
|
|
820
|
+
const g = this.children;
|
|
821
|
+
if (!this.childVisible && this.z >= i) {
|
|
822
|
+
const f = vn(h, n.zoom);
|
|
823
|
+
if (this.level.metersPerPixel * c / f <= 1 || this.z >= s || g === null && this.z >= i)
|
|
824
|
+
return this.selected = !0, !0;
|
|
825
|
+
}
|
|
826
|
+
if (g && g.length > 0) {
|
|
827
|
+
this.selected = !1;
|
|
828
|
+
let f = !1;
|
|
829
|
+
for (const y of g)
|
|
830
|
+
y.update(t) && (f = !0);
|
|
831
|
+
return this.childVisible = f, f;
|
|
832
|
+
}
|
|
833
|
+
return !0;
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Collect all tiles marked as selected in the tree.
|
|
837
|
+
* Recursively traverses the entire tree and gathers tiles where selected=true.
|
|
838
|
+
*
|
|
839
|
+
* @param result - Accumulator array for selected tiles
|
|
840
|
+
* @returns Array of selected RasterTileNode tiles
|
|
841
|
+
*/
|
|
842
|
+
getSelected(t = []) {
|
|
843
|
+
if (this.selected && t.push(this), this._children)
|
|
844
|
+
for (const n of this._children)
|
|
845
|
+
n.getSelected(t);
|
|
846
|
+
return t;
|
|
847
|
+
}
|
|
848
|
+
/**
|
|
849
|
+
* Test if this tile intersects the specified bounds in Web Mercator space.
|
|
850
|
+
* Used to filter tiles when only a specific geographic region is needed.
|
|
851
|
+
*
|
|
852
|
+
* @param bounds - [minX, minY, maxX, maxY] in Web Mercator units (0-512)
|
|
853
|
+
* @returns true if tile overlaps the bounds
|
|
854
|
+
*/
|
|
855
|
+
insideBounds(t, n) {
|
|
856
|
+
const [r, o, i, s] = t, [a, l, c, u] = n;
|
|
857
|
+
return a < i && c > r && l < s && u > o;
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* The 3D bounding volume for this tile in deck.gl's common coordinate space,
|
|
861
|
+
* used for frustum culling.
|
|
862
|
+
*
|
|
863
|
+
* Memoized in `boundingVolumeCache` (keyed by `z/x/y`): a tile's bounding
|
|
864
|
+
* volume depends only on `(z, x, y, zRange)` for a given descriptor, so on a
|
|
865
|
+
* cache hit it is returned without rerunning {@link computeBoundingVolume}'s
|
|
866
|
+
* proj4 reprojections + oriented-bounding-box fit.
|
|
867
|
+
*/
|
|
868
|
+
getBoundingVolume(t, n, r) {
|
|
869
|
+
const o = r.get(this.z, this.x, this.y);
|
|
870
|
+
if (o && o.zRange[0] === t[0] && o.zRange[1] === t[1])
|
|
871
|
+
return o;
|
|
872
|
+
const i = this.computeBoundingVolume(t, n);
|
|
873
|
+
return r.set(this.z, this.x, this.y, { zRange: t, ...i }), i;
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Compute (without caching) the 3D bounding volume for this tile in deck.gl's
|
|
877
|
+
* common coordinate space.
|
|
878
|
+
*
|
|
879
|
+
* TODO: In the future, we can add a fast path in the case that the source
|
|
880
|
+
* tiling is already in EPSG:3857.
|
|
881
|
+
*/
|
|
882
|
+
computeBoundingVolume(t, n) {
|
|
883
|
+
return n && Ut(!1, "TODO: implement getBoundingVolume in Globe view"), this._getGenericBoundingVolume(t);
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Generic case - sample reference points and reproject to Web Mercator, then
|
|
887
|
+
* convert to deck.gl common space
|
|
888
|
+
*
|
|
889
|
+
*/
|
|
890
|
+
_getGenericBoundingVolume(t) {
|
|
891
|
+
const [n, r] = t, o = this.level.projectedTileCorners(this.x, this.y), s = gn(pn, o, this.descriptor.projectTo3857, this.descriptor.projectTo4326).map((d) => fn(d)), a = [];
|
|
892
|
+
for (const d of s)
|
|
893
|
+
a.push([d[0], d[1], n]), n !== r && a.push([d[0], d[1], r]);
|
|
894
|
+
let l = Number.POSITIVE_INFINITY, c = Number.POSITIVE_INFINITY, u = Number.NEGATIVE_INFINITY, h = Number.NEGATIVE_INFINITY;
|
|
895
|
+
for (const [d, g] of s)
|
|
896
|
+
d < l && (l = d), g < c && (c = g), d > u && (u = d), g > h && (h = g);
|
|
897
|
+
const p = [l, c, u, h];
|
|
898
|
+
return {
|
|
899
|
+
boundingVolume: Bt(a),
|
|
900
|
+
commonSpaceBounds: p
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
function mn(e, t) {
|
|
905
|
+
return (n, r) => {
|
|
906
|
+
const [o, i] = e(n, r);
|
|
907
|
+
if (Number.isFinite(o) && Number.isFinite(i))
|
|
908
|
+
return [o, i];
|
|
909
|
+
const [s, a] = t(n, r), c = Math.max(-Ne, Math.min(Ne, a)) * Math.PI / 180, u = s * Math.PI * me / 180, h = Math.log(Math.tan(Math.PI / 4 + c / 2)) * me;
|
|
910
|
+
return [u, h];
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
function gn(e, t, n, r) {
|
|
914
|
+
const { topLeft: o, topRight: i, bottomLeft: s, bottomRight: a } = t, l = mn(n, r), c = [];
|
|
915
|
+
for (const [u, h] of e) {
|
|
916
|
+
const [p, d] = Ln(o, i, s, a, u, h);
|
|
917
|
+
c.push(l(p, d));
|
|
918
|
+
}
|
|
919
|
+
return c;
|
|
920
|
+
}
|
|
921
|
+
function fn([e, t]) {
|
|
922
|
+
const n = Math.max(-De, Math.min(De, t));
|
|
923
|
+
return [
|
|
924
|
+
(e / ge + 0.5) * Fe,
|
|
925
|
+
(n / ge + 0.5) * Fe
|
|
926
|
+
];
|
|
927
|
+
}
|
|
928
|
+
const yn = 100;
|
|
929
|
+
function wn(e) {
|
|
930
|
+
const { descriptor: t, viewport: n, datasetWgs84Bounds: r } = e, o = t.levels[0], i = [];
|
|
931
|
+
if (o.matrixWidth * o.matrixHeight <= yn) {
|
|
932
|
+
for (let g = 0; g < o.matrixHeight; g++)
|
|
933
|
+
for (let f = 0; f < o.matrixWidth; f++)
|
|
934
|
+
i.push(new ie(f, g, 0, { descriptor: t }));
|
|
935
|
+
return i;
|
|
936
|
+
}
|
|
937
|
+
const a = n.getBounds(), l = [
|
|
938
|
+
Math.max(r[0], a[0]),
|
|
939
|
+
Math.max(r[1], a[1]),
|
|
940
|
+
Math.min(r[2], a[2]),
|
|
941
|
+
Math.min(r[3], a[3])
|
|
942
|
+
];
|
|
943
|
+
if (l[0] > l[2] || l[1] > l[3])
|
|
944
|
+
return i;
|
|
945
|
+
const [c, u, h, p] = pe(t.projectFrom4326, l[0], l[1], l[2], l[3]), d = o.crsBoundsToTileRange(c, u, h, p);
|
|
946
|
+
for (let g = d.minRow; g <= d.maxRow; g++)
|
|
947
|
+
for (let f = d.minCol; f <= d.maxCol; f++)
|
|
948
|
+
i.push(new ie(f, g, 0, { descriptor: t }));
|
|
949
|
+
return i;
|
|
950
|
+
}
|
|
951
|
+
function Pn(e, t) {
|
|
952
|
+
const { viewport: n, maxZ: r, zRange: o, wgs84Bounds: i, pixelRatio: s = 1 } = t, a = t.boundingVolumeCache ?? new it();
|
|
953
|
+
a.sweep();
|
|
954
|
+
const l = n instanceof Ft && n.resolution ? n.projectPosition : null, c = Object.values(n.getFrustumPlanes()).map(({ normal: I, distance: J }) => new Dt(I.clone().negate(), J)), u = new Nt(c), h = n.distanceScales.unitsPerMeter[2], p = o && o[0] * h || 0, d = o && o[1] * h || 0, g = 0, [f, y, j, b] = i, S = Ee([f, y]), v = Ee([j, b]), L = [
|
|
955
|
+
S[0],
|
|
956
|
+
S[1],
|
|
957
|
+
v[0],
|
|
958
|
+
v[1]
|
|
959
|
+
], E = wn({
|
|
960
|
+
descriptor: e,
|
|
961
|
+
viewport: n,
|
|
962
|
+
datasetWgs84Bounds: i
|
|
963
|
+
}), M = {
|
|
964
|
+
viewport: n,
|
|
965
|
+
project: l,
|
|
966
|
+
cullingVolume: u,
|
|
967
|
+
elevationBounds: [p, d],
|
|
968
|
+
minZ: g,
|
|
969
|
+
maxZ: r,
|
|
970
|
+
bounds: L,
|
|
971
|
+
pixelRatio: s,
|
|
972
|
+
boundingVolumeCache: a
|
|
973
|
+
};
|
|
974
|
+
for (const I of E)
|
|
975
|
+
I.update(M);
|
|
976
|
+
const z = [];
|
|
977
|
+
for (const I of E)
|
|
978
|
+
I.getSelected(z);
|
|
979
|
+
return z;
|
|
980
|
+
}
|
|
981
|
+
function bn(e, t) {
|
|
982
|
+
return 40075016686e-3 * Math.cos(e * Math.PI / 180) / 2 ** (t + 8);
|
|
983
|
+
}
|
|
984
|
+
function vn(e, t) {
|
|
985
|
+
const [n, r] = Gt(e.center);
|
|
986
|
+
return bn(r, t);
|
|
987
|
+
}
|
|
988
|
+
function Sn({ topLeft: e, topRight: t, bottomLeft: n, bottomRight: r }) {
|
|
989
|
+
const o = [e[0], t[0], n[0], r[0]], i = [e[1], t[1], n[1], r[1]];
|
|
990
|
+
return [Math.min(...o), Math.min(...i), Math.max(...o), Math.max(...i)];
|
|
991
|
+
}
|
|
992
|
+
function Ln(e, t, n, r, o, i) {
|
|
993
|
+
const s = (1 - o) * (1 - i), a = o * (1 - i), l = (1 - o) * i, c = o * i;
|
|
994
|
+
return [
|
|
995
|
+
e[0] * s + t[0] * a + n[0] * l + r[0] * c,
|
|
996
|
+
e[1] * s + t[1] * a + n[1] * l + r[1] * c
|
|
997
|
+
];
|
|
998
|
+
}
|
|
999
|
+
function Cn(e, t) {
|
|
1000
|
+
const n = e.length;
|
|
1001
|
+
if (n < 2)
|
|
1002
|
+
return e;
|
|
1003
|
+
const { getCenter: r, reference: o } = t, i = o[0], s = o[1], a = new Float64Array(n);
|
|
1004
|
+
for (let u = 0; u < n; u++) {
|
|
1005
|
+
const h = r(e[u]), p = h[0] - i, d = h[1] - s;
|
|
1006
|
+
a[u] = p * p + d * d;
|
|
1007
|
+
}
|
|
1008
|
+
const l = new Uint32Array(n);
|
|
1009
|
+
for (let u = 0; u < n; u++)
|
|
1010
|
+
l[u] = u;
|
|
1011
|
+
l.sort((u, h) => a[u] - a[h]);
|
|
1012
|
+
const c = e.slice();
|
|
1013
|
+
for (let u = 0; u < n; u++)
|
|
1014
|
+
e[u] = c[l[u]];
|
|
1015
|
+
return e;
|
|
1016
|
+
}
|
|
1017
|
+
function jn(e, t, n) {
|
|
1018
|
+
const [r, o, i, s] = t.getBounds(), a = [
|
|
1019
|
+
(r + i) / 2,
|
|
1020
|
+
(o + s) / 2
|
|
1021
|
+
];
|
|
1022
|
+
return Cn(e, {
|
|
1023
|
+
reference: a,
|
|
1024
|
+
getCenter: n
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
class xn extends Kt {
|
|
1028
|
+
descriptor;
|
|
1029
|
+
wgs84Bounds;
|
|
1030
|
+
getPixelRatio;
|
|
1031
|
+
boundingVolumeCache;
|
|
1032
|
+
constructor(t, n, { getPixelRatio: r, maxBoundingVolumeCacheSize: o } = {}) {
|
|
1033
|
+
super(t), this.descriptor = n, this.getPixelRatio = r ?? (() => 1), this.boundingVolumeCache = new it({
|
|
1034
|
+
maxEntries: o
|
|
1035
|
+
});
|
|
1036
|
+
const i = pe(this.descriptor.projectTo4326, ...this.descriptor.projectedBounds), s = 85.0511287798066;
|
|
1037
|
+
this.wgs84Bounds = [
|
|
1038
|
+
i[0],
|
|
1039
|
+
Math.max(i[1], -s),
|
|
1040
|
+
i[2],
|
|
1041
|
+
Math.min(i[3], s)
|
|
1042
|
+
];
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Get tile indices visible in viewport
|
|
1046
|
+
* Uses frustum culling similar to OSM implementation
|
|
1047
|
+
*
|
|
1048
|
+
* Overviews follow TileMatrixSet ordering: index 0 = coarsest, higher = finer
|
|
1049
|
+
*
|
|
1050
|
+
* `minZoom` and `maxZoom` gate against `viewport.zoom` (not the tileset
|
|
1051
|
+
* z-index, which is an overview level in our descriptor). When the
|
|
1052
|
+
* viewport zoom is outside these bounds this method returns an empty
|
|
1053
|
+
* list — no new tile fetches, and because deck.gl's `updateTileStates`
|
|
1054
|
+
* marks unselected cached tiles invisible, no rendering either.
|
|
1055
|
+
* `visibleMinZoom` / `visibleMaxZoom` (deck.gl 9.3+) are deliberately
|
|
1056
|
+
* not honored: their documented "fetch but don't render" semantic
|
|
1057
|
+
* requires a notion of clamping to a coarser z, which doesn't
|
|
1058
|
+
* generalize to descriptors with sparse or single overviews. See
|
|
1059
|
+
* `dev-docs/zoom-terminology.md` for the rationale.
|
|
1060
|
+
*/
|
|
1061
|
+
getTileIndices(t) {
|
|
1062
|
+
const { viewport: n, minZoom: r } = t;
|
|
1063
|
+
if (typeof r == "number" && n.zoom < r)
|
|
1064
|
+
return [];
|
|
1065
|
+
const o = this.descriptor.levels.length - 1, i = typeof t.maxZoom == "number" ? Math.min(t.maxZoom, o) : o, s = Pn(this.descriptor, {
|
|
1066
|
+
viewport: n,
|
|
1067
|
+
maxZ: i,
|
|
1068
|
+
zRange: t.zRange ?? null,
|
|
1069
|
+
wgs84Bounds: this.wgs84Bounds,
|
|
1070
|
+
pixelRatio: this.getPixelRatio(),
|
|
1071
|
+
boundingVolumeCache: this.boundingVolumeCache
|
|
1072
|
+
});
|
|
1073
|
+
return this.sortTileIndicesByDistance(s, n);
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Sort tile indices by ascending distance from the viewport center in
|
|
1077
|
+
* projected (common/world) space so loads initiate center-out.
|
|
1078
|
+
*
|
|
1079
|
+
* Short-circuits when `tileIndices.length <= maxRequests` — all fetches
|
|
1080
|
+
* would start concurrently regardless of order in that case. Mutates and
|
|
1081
|
+
* returns `tileIndices`.
|
|
1082
|
+
*/
|
|
1083
|
+
sortTileIndicesByDistance(t, n) {
|
|
1084
|
+
const { maxRequests: r } = this.opts;
|
|
1085
|
+
if (t.length <= r)
|
|
1086
|
+
return t;
|
|
1087
|
+
const o = this.descriptor;
|
|
1088
|
+
return jn(t, n, (i) => {
|
|
1089
|
+
const { x: s, y: a, z: l } = i, { topLeft: c, bottomRight: u } = o.levels[l].projectedTileCorners(s, a), h = [
|
|
1090
|
+
(c[0] + u[0]) / 2,
|
|
1091
|
+
(c[1] + u[1]) / 2
|
|
1092
|
+
];
|
|
1093
|
+
return o.projectTo4326(h[0], h[1]);
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
getTileId(t) {
|
|
1097
|
+
return `${t.x}-${t.y}-${t.z}`;
|
|
1098
|
+
}
|
|
1099
|
+
getParentIndex(t) {
|
|
1100
|
+
if (t.z === 0)
|
|
1101
|
+
return t;
|
|
1102
|
+
const n = this.descriptor.levels[t.z], r = this.descriptor.levels[t.z - 1], o = r.metersPerPixel * r.tileWidth, i = r.metersPerPixel * r.tileHeight, s = n.metersPerPixel * n.tileWidth, a = n.metersPerPixel * n.tileHeight, l = o / s, c = i / a;
|
|
1103
|
+
return {
|
|
1104
|
+
x: Math.floor(t.x / l),
|
|
1105
|
+
y: Math.floor(t.y / c),
|
|
1106
|
+
z: t.z - 1
|
|
1107
|
+
};
|
|
1108
|
+
}
|
|
1109
|
+
getTileZoom(t) {
|
|
1110
|
+
return t.z;
|
|
1111
|
+
}
|
|
1112
|
+
getTileMetadata(t) {
|
|
1113
|
+
const { x: n, y: r, z: o } = t, i = this.descriptor.levels[o], { tileHeight: s, tileWidth: a } = i, { topLeft: l, topRight: c, bottomLeft: u, bottomRight: h } = i.projectedTileCorners(n, r), p = {
|
|
1114
|
+
topLeft: l,
|
|
1115
|
+
topRight: c,
|
|
1116
|
+
bottomLeft: u,
|
|
1117
|
+
bottomRight: h
|
|
1118
|
+
}, d = [
|
|
1119
|
+
Math.min(l[0], c[0], u[0], h[0]),
|
|
1120
|
+
Math.min(l[1], c[1], u[1], h[1]),
|
|
1121
|
+
Math.max(l[0], c[0], u[0], h[0]),
|
|
1122
|
+
Math.max(l[1], c[1], u[1], h[1])
|
|
1123
|
+
], [g, f, y, j] = pe(this.descriptor.projectTo4326, ...d), { forwardTransform: b, inverseTransform: S } = i.tileTransform(n, r);
|
|
1124
|
+
return {
|
|
1125
|
+
bbox: {
|
|
1126
|
+
west: g,
|
|
1127
|
+
south: f,
|
|
1128
|
+
east: y,
|
|
1129
|
+
north: j
|
|
1130
|
+
},
|
|
1131
|
+
projectedBbox: {
|
|
1132
|
+
left: d[0],
|
|
1133
|
+
bottom: d[1],
|
|
1134
|
+
right: d[2],
|
|
1135
|
+
top: d[3]
|
|
1136
|
+
},
|
|
1137
|
+
projectedCorners: p,
|
|
1138
|
+
tileWidth: a,
|
|
1139
|
+
tileHeight: s,
|
|
1140
|
+
forwardTransform: b,
|
|
1141
|
+
inverseTransform: S
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
const fe = 512, On = 40075016686e-3, Ue = fe / On, An = {
|
|
1146
|
+
...rt.defaultProps,
|
|
1147
|
+
maxError: 0.125,
|
|
1148
|
+
debug: !1,
|
|
1149
|
+
debugOpacity: 0.5
|
|
1150
|
+
};
|
|
1151
|
+
class Be extends nt {
|
|
1152
|
+
static layerName = "RasterTileLayer";
|
|
1153
|
+
static defaultProps = An;
|
|
1154
|
+
/**
|
|
1155
|
+
* The currently effective {@link RasterTilesetDescriptor}.
|
|
1156
|
+
*
|
|
1157
|
+
* Subclasses override this to return a descriptor built from their own
|
|
1158
|
+
* async-parsed state. Returns `undefined` while the source is still
|
|
1159
|
+
* loading; `renderLayers()` returns `null` in that case.
|
|
1160
|
+
*
|
|
1161
|
+
* The inline cast to `RasterTileLayerProps<DataT>` is required because
|
|
1162
|
+
* `tilesetDescriptor` is declared on `ExtraProps`, not on the base's
|
|
1163
|
+
* `RasterTileLayerBaseProps`. For direct use the default `ExtraProps`
|
|
1164
|
+
* brings it in; for subclass use this method is overridden and the cast
|
|
1165
|
+
* is never reached.
|
|
1166
|
+
*/
|
|
1167
|
+
_tilesetDescriptor() {
|
|
1168
|
+
return this.props.tilesetDescriptor;
|
|
1169
|
+
}
|
|
1170
|
+
/**
|
|
1171
|
+
* The currently effective tile-fetch callback.
|
|
1172
|
+
*
|
|
1173
|
+
* Subclasses override this to adapt their user-facing `getTileData`
|
|
1174
|
+
* signature into the base's `(tile, options) => Promise<DataT>` shape.
|
|
1175
|
+
* Returns `undefined` when the callback is not yet available.
|
|
1176
|
+
*/
|
|
1177
|
+
_getTileDataCallback() {
|
|
1178
|
+
return this.props.getTileData;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* The currently effective per-tile render callback.
|
|
1182
|
+
*
|
|
1183
|
+
* Subclasses override this to thread their user-facing `renderTile` and
|
|
1184
|
+
* any inferred default. Returns `undefined` when no callback is available.
|
|
1185
|
+
*/
|
|
1186
|
+
_renderTileCallback() {
|
|
1187
|
+
return this.props.renderTile;
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Hook for rendering per-tile debug overlay sub-layers.
|
|
1191
|
+
*
|
|
1192
|
+
* Called once per tile from `_renderSubLayers` only when `props.debug` is
|
|
1193
|
+
* `true`. The hook fires both before data has arrived (`data` is `null`) and
|
|
1194
|
+
* after (`data` is the fetched `DataT`), so the default outline can render
|
|
1195
|
+
* during loading.
|
|
1196
|
+
*
|
|
1197
|
+
* Default behavior renders the primary tile boundary via
|
|
1198
|
+
* {@link renderDebugTileOutline} using the active descriptor. Subclasses can
|
|
1199
|
+
* override to replace, extend (via `super._renderDebug(...)`), or suppress
|
|
1200
|
+
* the default — for example, a multi-source layer can replace the default
|
|
1201
|
+
* with per-band tile outlines and tiered metadata labels once `data` is
|
|
1202
|
+
* available.
|
|
1203
|
+
*/
|
|
1204
|
+
_renderDebug(t, n) {
|
|
1205
|
+
const r = this._tilesetDescriptor();
|
|
1206
|
+
return r ? Xt(`${this.id}-${t.id}-bounds`, t, r.projectTo4326) : [];
|
|
1207
|
+
}
|
|
1208
|
+
renderLayers() {
|
|
1209
|
+
const t = this._tilesetDescriptor(), n = this._getTileDataCallback(), r = this._renderTileCallback();
|
|
1210
|
+
return !t || !n || !r ? null : this._renderTileLayer(t, n, r);
|
|
1211
|
+
}
|
|
1212
|
+
_renderTileLayer(t, n, r) {
|
|
1213
|
+
const o = this.context.device;
|
|
1214
|
+
class i extends xn {
|
|
1215
|
+
constructor(E) {
|
|
1216
|
+
super(E, t, {
|
|
1217
|
+
getPixelRatio: () => {
|
|
1218
|
+
const M = o.getDefaultCanvasContext(), [z] = M.getDrawingBufferSize(), [I] = M.getCSSSize();
|
|
1219
|
+
return I ? z / I : 1;
|
|
1220
|
+
}
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
const { tileSize: s, zoomOffset: a, maxZoom: l, minZoom: c, extent: u, debounceTime: h, maxCacheSize: p, maxCacheByteSize: d, maxRequests: g, refinementStrategy: f, updateTriggers: y, onTileError: j, onTileLoad: b, onTileUnload: S, onViewportLoad: v } = this.props;
|
|
1225
|
+
return new rt({
|
|
1226
|
+
id: `raster-tile-layer-${this.id}`,
|
|
1227
|
+
TilesetClass: i,
|
|
1228
|
+
getTileData: (L) => this._wrapGetTileData(L, n),
|
|
1229
|
+
renderSubLayers: (L) => this._renderSubLayers(L, t, r),
|
|
1230
|
+
updateTriggers: {
|
|
1231
|
+
renderSubLayers: y?.renderTile
|
|
1232
|
+
},
|
|
1233
|
+
tileSize: s,
|
|
1234
|
+
zoomOffset: a,
|
|
1235
|
+
maxZoom: l,
|
|
1236
|
+
minZoom: c,
|
|
1237
|
+
extent: u,
|
|
1238
|
+
debounceTime: h,
|
|
1239
|
+
maxCacheSize: p,
|
|
1240
|
+
maxCacheByteSize: d,
|
|
1241
|
+
maxRequests: g,
|
|
1242
|
+
refinementStrategy: f,
|
|
1243
|
+
onTileError: j,
|
|
1244
|
+
onTileLoad: b,
|
|
1245
|
+
onTileUnload: S,
|
|
1246
|
+
onViewportLoad: v
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
async _wrapGetTileData(t, n) {
|
|
1250
|
+
const { signal: r } = t, o = this.props.signal, i = o && r ? AbortSignal.any([o, r]) : o ?? r, s = {
|
|
1251
|
+
device: this.context.device,
|
|
1252
|
+
signal: i
|
|
1253
|
+
};
|
|
1254
|
+
return n(t, s);
|
|
1255
|
+
}
|
|
1256
|
+
_renderSubLayers(t, n, r) {
|
|
1257
|
+
const { maxError: o, debug: i, debugOpacity: s } = this.props, a = t.tile, l = i ? this._renderDebug(a, t.data ?? null) : [];
|
|
1258
|
+
if (!t.data)
|
|
1259
|
+
return l;
|
|
1260
|
+
const { forwardTransform: c, inverseTransform: u } = a, h = r(t.data);
|
|
1261
|
+
if (!h)
|
|
1262
|
+
return l;
|
|
1263
|
+
const { image: p, renderPipeline: d } = h, { width: g, height: f } = t.data, y = this.context.viewport.resolution !== void 0, j = y ? {
|
|
1264
|
+
forwardTransform: c,
|
|
1265
|
+
inverseTransform: u,
|
|
1266
|
+
forwardReproject: n.projectTo4326,
|
|
1267
|
+
inverseReproject: n.projectFrom4326
|
|
1268
|
+
} : {
|
|
1269
|
+
forwardTransform: c,
|
|
1270
|
+
inverseTransform: u,
|
|
1271
|
+
forwardReproject: n.projectTo3857,
|
|
1272
|
+
inverseReproject: n.projectFrom3857
|
|
1273
|
+
}, b = y ? {} : {
|
|
1274
|
+
coordinateSystem: "cartesian",
|
|
1275
|
+
coordinateOrigin: [fe / 2, fe / 2, 0],
|
|
1276
|
+
// biome-ignore format: array
|
|
1277
|
+
modelMatrix: [
|
|
1278
|
+
Ue,
|
|
1279
|
+
0,
|
|
1280
|
+
0,
|
|
1281
|
+
0,
|
|
1282
|
+
0,
|
|
1283
|
+
Ue,
|
|
1284
|
+
0,
|
|
1285
|
+
0,
|
|
1286
|
+
0,
|
|
1287
|
+
0,
|
|
1288
|
+
1,
|
|
1289
|
+
0,
|
|
1290
|
+
0,
|
|
1291
|
+
0,
|
|
1292
|
+
0,
|
|
1293
|
+
1
|
|
1294
|
+
]
|
|
1295
|
+
};
|
|
1296
|
+
return [new Tt(this.getSubLayerProps({
|
|
1297
|
+
id: `${t.id}-raster`,
|
|
1298
|
+
width: g,
|
|
1299
|
+
height: f,
|
|
1300
|
+
// Passing `image: undefined` explicitly would trip isAsyncPropLoading
|
|
1301
|
+
// and cause a transient black flash (see issue #376).
|
|
1302
|
+
...p !== void 0 && { image: p },
|
|
1303
|
+
renderPipeline: d,
|
|
1304
|
+
maxError: o,
|
|
1305
|
+
reprojectionFns: j,
|
|
1306
|
+
debug: i,
|
|
1307
|
+
debugOpacity: s,
|
|
1308
|
+
...b
|
|
1309
|
+
})), ...l];
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
function En(e, t) {
|
|
1313
|
+
const n = e.length / 3, r = new Uint8ClampedArray(n * 4), o = 0, i = n, s = n * 2;
|
|
1314
|
+
for (let a = 0; a < n; a++)
|
|
1315
|
+
r[4 * a + 0] = e[o + a] >> 8, r[4 * a + 1] = e[i + a] >> 8, r[4 * a + 2] = e[s + a] >> 8, r[4 * a + 3] = 255;
|
|
1316
|
+
return new ImageData(r, n, 1);
|
|
1317
|
+
}
|
|
1318
|
+
var ye;
|
|
1319
|
+
(function(e) {
|
|
1320
|
+
e[e.Big = 19789] = "Big", e[e.Little = 18761] = "Little";
|
|
1321
|
+
})(ye || (ye = {}));
|
|
1322
|
+
var $;
|
|
1323
|
+
(function(e) {
|
|
1324
|
+
e[e.ReducedImage = 1] = "ReducedImage", e[e.Page = 2] = "Page", e[e.Mask = 4] = "Mask";
|
|
1325
|
+
})($ || ($ = {}));
|
|
1326
|
+
var Ge;
|
|
1327
|
+
(function(e) {
|
|
1328
|
+
e[e.TopLeft = 1] = "TopLeft", e[e.TopRight = 2] = "TopRight", e[e.BottomRight = 3] = "BottomRight", e[e.BottomLeft = 4] = "BottomLeft", e[e.LeftTop = 5] = "LeftTop", e[e.RightTOP = 6] = "RightTOP", e[e.RightBottom = 7] = "RightBottom", e[e.LeftBottom = 8] = "LeftBottom";
|
|
1329
|
+
})(Ge || (Ge = {}));
|
|
1330
|
+
var we;
|
|
1331
|
+
(function(e) {
|
|
1332
|
+
e[e.PixelIsArea = 1] = "PixelIsArea", e[e.PixelIsPoint = 2] = "PixelIsPoint";
|
|
1333
|
+
})(we || (we = {}));
|
|
1334
|
+
var G;
|
|
1335
|
+
(function(e) {
|
|
1336
|
+
e[e.Unknown = 0] = "Unknown", e[e.Projected = 1] = "Projected", e[e.Geographic = 2] = "Geographic", e[e.Geocentric = 3] = "Geocentric", e[e.UserDefined = 32767] = "UserDefined";
|
|
1337
|
+
})(G || (G = {}));
|
|
1338
|
+
var Ke;
|
|
1339
|
+
(function(e) {
|
|
1340
|
+
e[e.Image = 1] = "Image", e[e.ReducedImage = 2] = "ReducedImage", e[e.Page = 3] = "Page";
|
|
1341
|
+
})(Ke || (Ke = {}));
|
|
1342
|
+
var P;
|
|
1343
|
+
(function(e) {
|
|
1344
|
+
e[e.None = 1] = "None", e[e.Ccittrle = 2] = "Ccittrle", e[e.CcittT4 = 3] = "CcittT4", e[e.CcittT6 = 4] = "CcittT6", e[e.Lzw = 5] = "Lzw", e[e.Jpeg6 = 6] = "Jpeg6", e[e.Jpeg = 7] = "Jpeg", e[e.DeflateOther = 8] = "DeflateOther", e[e.T85 = 9] = "T85", e[e.T43 = 10] = "T43", e[e.Next = 32766] = "Next", e[e.Ccittrlew = 32771] = "Ccittrlew", e[e.PackBits = 32773] = "PackBits", e[e.ThunderScan = 32809] = "ThunderScan", e[e.It8ctpad = 32895] = "It8ctpad", e[e.It8lw = 32896] = "It8lw", e[e.It8mp = 32897] = "It8mp", e[e.It8bl = 32898] = "It8bl", e[e.PixarFilm = 32908] = "PixarFilm", e[e.PixarLog = 32909] = "PixarLog", e[e.Deflate = 32946] = "Deflate", e[e.Dcs = 32947] = "Dcs", e[e.Jbig = 34661] = "Jbig", e[e.SgiLog = 34676] = "SgiLog", e[e.SgiLog24 = 34677] = "SgiLog24", e[e.Jp2000 = 34712] = "Jp2000", e[e.Lerc = 34887] = "Lerc", e[e.Lzma = 34925] = "Lzma", e[e.Zstd = 5e4] = "Zstd", e[e.Webp = 50001] = "Webp", e[e.JpegXl = 50002] = "JpegXl", e[e.JpegXlDng17 = 52546] = "JpegXlDng17";
|
|
1345
|
+
})(P || (P = {}));
|
|
1346
|
+
var U;
|
|
1347
|
+
(function(e) {
|
|
1348
|
+
e[e.Contig = 1] = "Contig", e[e.Separate = 2] = "Separate";
|
|
1349
|
+
})(U || (U = {}));
|
|
1350
|
+
var V;
|
|
1351
|
+
(function(e) {
|
|
1352
|
+
e[e.None = 1] = "None", e[e.Horizontal = 2] = "Horizontal", e[e.FloatingPoint = 3] = "FloatingPoint";
|
|
1353
|
+
})(V || (V = {}));
|
|
1354
|
+
var F;
|
|
1355
|
+
(function(e) {
|
|
1356
|
+
e[e.Uint = 1] = "Uint", e[e.Int = 2] = "Int", e[e.Float = 3] = "Float", e[e.Void = 4] = "Void", e[e.ComplexInt = 5] = "ComplexInt", e[e.ComplexFloat = 6] = "ComplexFloat";
|
|
1357
|
+
})(F || (F = {}));
|
|
1358
|
+
var R;
|
|
1359
|
+
(function(e) {
|
|
1360
|
+
e[e.MinIsWhite = 0] = "MinIsWhite", e[e.MinIsBlack = 1] = "MinIsBlack", e[e.Rgb = 2] = "Rgb", e[e.Palette = 3] = "Palette", e[e.Mask = 4] = "Mask", e[e.Separated = 5] = "Separated", e[e.Ycbcr = 6] = "Ycbcr", e[e.Cielab = 8] = "Cielab", e[e.Icclab = 9] = "Icclab", e[e.Itulab = 10] = "Itulab", e[e.Cfa = 32803] = "Cfa", e[e.Logl = 32844] = "Logl", e[e.Logluv = 32845] = "Logluv";
|
|
1361
|
+
})(R || (R = {}));
|
|
1362
|
+
var m;
|
|
1363
|
+
(function(e) {
|
|
1364
|
+
e[e.SubFileType = 254] = "SubFileType", e[e.OldSubFileType = 255] = "OldSubFileType", e[e.ImageWidth = 256] = "ImageWidth", e[e.ImageHeight = 257] = "ImageHeight", e[e.BitsPerSample = 258] = "BitsPerSample", e[e.SampleFormat = 339] = "SampleFormat", e[e.Compression = 259] = "Compression", e[e.Photometric = 262] = "Photometric", e[e.TileWidth = 322] = "TileWidth", e[e.TileHeight = 323] = "TileHeight", e[e.TileOffsets = 324] = "TileOffsets", e[e.TileByteCounts = 325] = "TileByteCounts", e[e.JpegTables = 347] = "JpegTables", e[e.StripOffsets = 273] = "StripOffsets", e[e.StripByteCounts = 279] = "StripByteCounts", e[e.GdalMetadata = 42112] = "GdalMetadata", e[e.GdalNoData = 42113] = "GdalNoData", e[e.ModelPixelScale = 33550] = "ModelPixelScale", e[e.ModelTiePoint = 33922] = "ModelTiePoint", e[e.ModelTransformation = 34264] = "ModelTransformation", e[e.GeoKeyDirectory = 34735] = "GeoKeyDirectory", e[e.GeoDoubleParams = 34736] = "GeoDoubleParams", e[e.GeoAsciiParams = 34737] = "GeoAsciiParams", e[e.LercParameters = 50674] = "LercParameters", e[e.PlanarConfiguration = 284] = "PlanarConfiguration", e[e.CellLength = 265] = "CellLength", e[e.CellWidth = 264] = "CellWidth", e[e.ColorMap = 320] = "ColorMap", e[e.Copyright = 33432] = "Copyright", e[e.DateTime = 306] = "DateTime", e[e.ExtraSamples = 338] = "ExtraSamples", e[e.FillOrder = 266] = "FillOrder", e[e.FreeByteCounts = 289] = "FreeByteCounts", e[e.FreeOffsets = 288] = "FreeOffsets", e[e.GrayResponseCurve = 291] = "GrayResponseCurve", e[e.GrayResponseUnit = 290] = "GrayResponseUnit", e[e.HostComputer = 316] = "HostComputer", e[e.ImageDescription = 270] = "ImageDescription", e[e.Make = 271] = "Make", e[e.MaxSampleValue = 281] = "MaxSampleValue", e[e.MinSampleValue = 280] = "MinSampleValue", e[e.Model = 272] = "Model", e[e.Orientation = 274] = "Orientation", e[e.ResolutionUnit = 296] = "ResolutionUnit", e[e.RowsPerStrip = 278] = "RowsPerStrip", e[e.SamplesPerPixel = 277] = "SamplesPerPixel", e[e.Software = 305] = "Software", e[e.Threshholding = 263] = "Threshholding", e[e.XResolution = 282] = "XResolution", e[e.YResolution = 283] = "YResolution", e[e.BadFaxLines = 326] = "BadFaxLines", e[e.CleanFaxData = 327] = "CleanFaxData", e[e.ClipPath = 343] = "ClipPath", e[e.ConsecutiveBadFaxLines = 328] = "ConsecutiveBadFaxLines", e[e.Decode = 433] = "Decode", e[e.DefaultImageColor = 434] = "DefaultImageColor", e[e.DocumentName = 269] = "DocumentName", e[e.DotRange = 336] = "DotRange", e[e.HalftoneHints = 321] = "HalftoneHints", e[e.Indexed = 346] = "Indexed", e[e.PageName = 285] = "PageName", e[e.PageNumber = 297] = "PageNumber", e[e.Predictor = 317] = "Predictor", e[e.PrimaryChromaticities = 319] = "PrimaryChromaticities", e[e.ReferenceBlackWhite = 532] = "ReferenceBlackWhite", e[e.SMinSampleValue = 340] = "SMinSampleValue", e[e.SMaxSampleValue = 341] = "SMaxSampleValue", e[e.StripRowCounts = 559] = "StripRowCounts", e[e.SubIFDs = 330] = "SubIFDs", e[e.T4Options = 292] = "T4Options", e[e.T6Options = 293] = "T6Options", e[e.TransferFunction = 301] = "TransferFunction", e[e.WhitePoint = 318] = "WhitePoint", e[e.XClipPathUnits = 344] = "XClipPathUnits", e[e.XPosition = 286] = "XPosition", e[e.YCbCrCoefficients = 529] = "YCbCrCoefficients", e[e.YCbCrPositioning = 531] = "YCbCrPositioning", e[e.YCbCrSubSampling = 530] = "YCbCrSubSampling", e[e.YClipPathUnits = 345] = "YClipPathUnits", e[e.YPosition = 287] = "YPosition", e[e.ApertureValue = 37378] = "ApertureValue", e[e.ColorSpace = 40961] = "ColorSpace", e[e.DateTimeDigitized = 36868] = "DateTimeDigitized", e[e.DateTimeOriginal = 36867] = "DateTimeOriginal", e[e.ExifIFD = 34665] = "ExifIFD", e[e.ExifVersion = 36864] = "ExifVersion", e[e.ExposureTime = 33434] = "ExposureTime", e[e.FileSource = 41728] = "FileSource", e[e.Flash = 37385] = "Flash", e[e.FlashpixVersion = 40960] = "FlashpixVersion", e[e.FNumber = 33437] = "FNumber", e[e.ImageUniqueID = 42016] = "ImageUniqueID", e[e.LightSource = 37384] = "LightSource", e[e.MakerNote = 37500] = "MakerNote", e[e.ShutterSpeedValue = 37377] = "ShutterSpeedValue", e[e.UserComment = 37510] = "UserComment", e[e.IPTC = 33723] = "IPTC", e[e.ICCProfile = 34675] = "ICCProfile", e[e.XMP = 700] = "XMP";
|
|
1365
|
+
})(m || (m = {}));
|
|
1366
|
+
var w;
|
|
1367
|
+
(function(e) {
|
|
1368
|
+
e[e.GTModelTypeGeoKey = 1024] = "GTModelTypeGeoKey", e[e.GTRasterTypeGeoKey = 1025] = "GTRasterTypeGeoKey", e[e.GTCitationGeoKey = 1026] = "GTCitationGeoKey", e[e.GeodeticCRSGeoKey = 2048] = "GeodeticCRSGeoKey", e[e.GeodeticCitationGeoKey = 2049] = "GeodeticCitationGeoKey", e[e.GeodeticDatumGeoKey = 2050] = "GeodeticDatumGeoKey", e[e.PrimeMeridianGeoKey = 2051] = "PrimeMeridianGeoKey", e[e.GeogLinearUnitsGeoKey = 2052] = "GeogLinearUnitsGeoKey", e[e.GeogLinearUnitSizeGeoKey = 2053] = "GeogLinearUnitSizeGeoKey", e[e.GeogAngularUnitsGeoKey = 2054] = "GeogAngularUnitsGeoKey", e[e.GeogAngularUnitSizeGeoKey = 2055] = "GeogAngularUnitSizeGeoKey", e[e.EllipsoidGeoKey = 2056] = "EllipsoidGeoKey", e[e.EllipsoidSemiMajorAxisGeoKey = 2057] = "EllipsoidSemiMajorAxisGeoKey", e[e.EllipsoidSemiMinorAxisGeoKey = 2058] = "EllipsoidSemiMinorAxisGeoKey", e[e.EllipsoidInvFlatteningGeoKey = 2059] = "EllipsoidInvFlatteningGeoKey", e[e.PrimeMeridianLongitudeGeoKey = 2061] = "PrimeMeridianLongitudeGeoKey", e[e.GeogTOWGS84GeoKey = 2062] = "GeogTOWGS84GeoKey", e[e.GeogAzimuthUnitsGeoKey = 2060] = "GeogAzimuthUnitsGeoKey", e[e.ProjectedCRSGeoKey = 3072] = "ProjectedCRSGeoKey", e[e.ProjectedCitationGeoKey = 3073] = "ProjectedCitationGeoKey", e[e.ProjectionGeoKey = 3074] = "ProjectionGeoKey", e[e.ProjMethodGeoKey = 3075] = "ProjMethodGeoKey", e[e.ProjLinearUnitsGeoKey = 3076] = "ProjLinearUnitsGeoKey", e[e.ProjLinearUnitSizeGeoKey = 3077] = "ProjLinearUnitSizeGeoKey", e[e.ProjStdParallel1GeoKey = 3078] = "ProjStdParallel1GeoKey", e[e.ProjStdParallel2GeoKey = 3079] = "ProjStdParallel2GeoKey", e[e.ProjNatOriginLongGeoKey = 3080] = "ProjNatOriginLongGeoKey", e[e.ProjNatOriginLatGeoKey = 3081] = "ProjNatOriginLatGeoKey", e[e.ProjFalseEastingGeoKey = 3082] = "ProjFalseEastingGeoKey", e[e.ProjFalseNorthingGeoKey = 3083] = "ProjFalseNorthingGeoKey", e[e.ProjFalseOriginLongGeoKey = 3084] = "ProjFalseOriginLongGeoKey", e[e.ProjFalseOriginLatGeoKey = 3085] = "ProjFalseOriginLatGeoKey", e[e.ProjFalseOriginEastingGeoKey = 3086] = "ProjFalseOriginEastingGeoKey", e[e.ProjFalseOriginNorthingGeoKey = 3087] = "ProjFalseOriginNorthingGeoKey", e[e.ProjCenterLongGeoKey = 3088] = "ProjCenterLongGeoKey", e[e.ProjCenterLatGeoKey = 3089] = "ProjCenterLatGeoKey", e[e.ProjCenterEastingGeoKey = 3090] = "ProjCenterEastingGeoKey", e[e.ProjCenterNorthingGeoKey = 3091] = "ProjCenterNorthingGeoKey", e[e.ProjScaleAtNatOriginGeoKey = 3092] = "ProjScaleAtNatOriginGeoKey", e[e.ProjScaleAtCenterGeoKey = 3093] = "ProjScaleAtCenterGeoKey", e[e.ProjAzimuthAngleGeoKey = 3094] = "ProjAzimuthAngleGeoKey", e[e.ProjStraightVertPoleLongGeoKey = 3095] = "ProjStraightVertPoleLongGeoKey", e[e.ProjRectifiedGridAngleGeoKey = 3096] = "ProjRectifiedGridAngleGeoKey", e[e.VerticalGeoKey = 4096] = "VerticalGeoKey", e[e.VerticalCitationGeoKey = 4097] = "VerticalCitationGeoKey", e[e.VerticalDatumGeoKey = 4098] = "VerticalDatumGeoKey", e[e.VerticalUnitsGeoKey = 4099] = "VerticalUnitsGeoKey";
|
|
1369
|
+
})(w || (w = {}));
|
|
1370
|
+
var _e;
|
|
1371
|
+
(function(e) {
|
|
1372
|
+
e[e.Radian = 9101] = "Radian", e[e.Degree = 9102] = "Degree", e[e.ArcMinute = 9103] = "ArcMinute", e[e.ArcDegree = 9104] = "ArcDegree", e[e.Grad = 9105] = "Grad", e[e.Gon = 9106] = "Gon", e[e.Dms = 9107] = "Dms";
|
|
1373
|
+
})(_e || (_e = {}));
|
|
1374
|
+
var Xe;
|
|
1375
|
+
(function(e) {
|
|
1376
|
+
e[e.Metre = 9001] = "Metre", e[e.Foot = 9002] = "Foot", e[e.FootUsSurvey = 9003] = "FootUsSurvey", e[e.FootModifiedAmerican = 9004] = "FootModifiedAmerican", e[e.FootClarke = 9005] = "FootClarke", e[e.FootIndian = 9006] = "FootIndian", e[e.Link = 9007] = "Link", e[e.LinkBenoit = 9008] = "LinkBenoit", e[e.LinkSears = 9009] = "LinkSears", e[e.ChainBenoit = 9010] = "ChainBenoit", e[e.ChainSears = 9011] = "ChainSears", e[e.YardSears = 9012] = "YardSears", e[e.YardIndian = 9013] = "YardIndian", e[e.Fathom = 9014] = "Fathom", e[e.MileInternationalNautical = 9015] = "MileInternationalNautical";
|
|
1377
|
+
})(Xe || (Xe = {}));
|
|
1378
|
+
const In = {
|
|
1379
|
+
[m.TileByteCounts]: !0,
|
|
1380
|
+
[m.TileOffsets]: !0,
|
|
1381
|
+
[m.StripOffsets]: !0,
|
|
1382
|
+
[m.StripByteCounts]: !0,
|
|
1383
|
+
[m.BitsPerSample]: !0,
|
|
1384
|
+
[m.SampleFormat]: !0,
|
|
1385
|
+
[m.GeoKeyDirectory]: !0,
|
|
1386
|
+
[m.GeoDoubleParams]: !0
|
|
1387
|
+
};
|
|
1388
|
+
var x;
|
|
1389
|
+
(function(e) {
|
|
1390
|
+
e.None = "application/octet-stream", e.Jbig = "image/jbig", e.Dcs = "image/x-kodak-dcs", e.PackBits = "application/packbits", e.Jpeg = "image/jpeg", e.Jp2000 = "image/jp2", e.JpegXl = "image/jpegxl", e.Webp = "image/webp", e.Zstd = "application/zstd", e.Lzw = "application/lzw", e.Deflate = "application/deflate", e.Lerc = "application/lerc", e.Lzma = "application/x-lzma";
|
|
1391
|
+
})(x || (x = {}));
|
|
1392
|
+
const st = {
|
|
1393
|
+
[P.None]: x.None,
|
|
1394
|
+
[P.Lzw]: x.Lzw,
|
|
1395
|
+
[P.Jpeg6]: x.Jpeg,
|
|
1396
|
+
[P.Jpeg]: x.Jpeg,
|
|
1397
|
+
[P.DeflateOther]: x.Deflate,
|
|
1398
|
+
[P.Deflate]: x.Deflate,
|
|
1399
|
+
[P.Lerc]: x.Lerc,
|
|
1400
|
+
[P.Lzma]: x.Lzma,
|
|
1401
|
+
[P.Jp2000]: x.Jp2000,
|
|
1402
|
+
[P.Zstd]: x.Zstd,
|
|
1403
|
+
[P.Webp]: x.Webp,
|
|
1404
|
+
[P.JpegXl]: x.JpegXl,
|
|
1405
|
+
[P.Ccittrle]: x.None,
|
|
1406
|
+
[P.CcittT4]: x.None,
|
|
1407
|
+
[P.CcittT6]: x.None,
|
|
1408
|
+
[P.T85]: x.Jbig,
|
|
1409
|
+
[P.T43]: x.Jbig,
|
|
1410
|
+
[P.Next]: x.None,
|
|
1411
|
+
[P.Ccittrlew]: x.None,
|
|
1412
|
+
[P.PackBits]: x.PackBits,
|
|
1413
|
+
[P.ThunderScan]: x.None,
|
|
1414
|
+
[P.It8ctpad]: x.None,
|
|
1415
|
+
[P.It8lw]: x.None,
|
|
1416
|
+
[P.It8mp]: x.None,
|
|
1417
|
+
[P.It8bl]: x.None,
|
|
1418
|
+
[P.PixarFilm]: x.None,
|
|
1419
|
+
[P.PixarLog]: x.None,
|
|
1420
|
+
[P.Dcs]: x.Dcs,
|
|
1421
|
+
[P.Jbig]: x.Jbig,
|
|
1422
|
+
[P.SgiLog]: x.None,
|
|
1423
|
+
[P.SgiLog24]: x.None,
|
|
1424
|
+
[P.JpegXlDng17]: x.JpegXl
|
|
1425
|
+
};
|
|
1426
|
+
function Mn(e) {
|
|
1427
|
+
return e == null ? null : st[e];
|
|
1428
|
+
}
|
|
1429
|
+
var C;
|
|
1430
|
+
(function(e) {
|
|
1431
|
+
e[e.Uint8 = 1] = "Uint8", e[e.Ascii = 2] = "Ascii", e[e.Uint16 = 3] = "Uint16", e[e.Uint32 = 4] = "Uint32", e[e.Rational = 5] = "Rational", e[e.Int8 = 6] = "Int8", e[e.Undefined = 7] = "Undefined", e[e.Int16 = 8] = "Int16", e[e.Int32 = 9] = "Int32", e[e.SignedRational = 10] = "SignedRational", e[e.Float32 = 11] = "Float32", e[e.Float64 = 12] = "Float64", e[e.Ifd = 13] = "Ifd", e[e.Uint64 = 16] = "Uint64", e[e.Int64 = 17] = "Int64", e[e.Ifd8 = 18] = "Ifd8";
|
|
1432
|
+
})(C || (C = {}));
|
|
1433
|
+
var N;
|
|
1434
|
+
(function(e) {
|
|
1435
|
+
e[e.BigTiff = 43] = "BigTiff", e[e.Tiff = 42] = "Tiff";
|
|
1436
|
+
})(N || (N = {}));
|
|
1437
|
+
function W(e) {
|
|
1438
|
+
switch (e) {
|
|
1439
|
+
case C.Uint8:
|
|
1440
|
+
case C.Ascii:
|
|
1441
|
+
case C.Int8:
|
|
1442
|
+
case C.Undefined:
|
|
1443
|
+
return 1;
|
|
1444
|
+
case C.Uint16:
|
|
1445
|
+
case C.Int16:
|
|
1446
|
+
return 2;
|
|
1447
|
+
case C.Uint32:
|
|
1448
|
+
case C.Int32:
|
|
1449
|
+
case C.Float32:
|
|
1450
|
+
case C.Ifd:
|
|
1451
|
+
return 4;
|
|
1452
|
+
case C.Rational:
|
|
1453
|
+
case C.SignedRational:
|
|
1454
|
+
case C.Float64:
|
|
1455
|
+
case C.Uint64:
|
|
1456
|
+
case C.Int64:
|
|
1457
|
+
case C.Ifd8:
|
|
1458
|
+
return 8;
|
|
1459
|
+
default:
|
|
1460
|
+
throw new Error(`Invalid fieldType ${String(e)}`);
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
var We;
|
|
1464
|
+
(function(e) {
|
|
1465
|
+
e[e.Double = 8] = "Double", e[e.Float32 = 4] = "Float32";
|
|
1466
|
+
})(We || (We = {}));
|
|
1467
|
+
var O;
|
|
1468
|
+
(function(e) {
|
|
1469
|
+
e[e.UInt64 = 8] = "UInt64", e[e.UInt32 = 4] = "UInt32", e[e.UInt16 = 2] = "UInt16", e[e.UInt8 = 1] = "UInt8";
|
|
1470
|
+
})(O || (O = {}));
|
|
1471
|
+
const He = 2 ** 32;
|
|
1472
|
+
function at(e, t, n) {
|
|
1473
|
+
const r = e.getUint32(t, n), o = e.getUint32(t + 4, n), i = n ? r + He * o : He * r + o;
|
|
1474
|
+
if (!Number.isSafeInteger(i))
|
|
1475
|
+
throw new Error(i + " exceeds MAX_SAFE_INTEGER. Precision may is lost");
|
|
1476
|
+
return i;
|
|
1477
|
+
}
|
|
1478
|
+
function K(e, t, n, r) {
|
|
1479
|
+
switch (n) {
|
|
1480
|
+
case O.UInt8:
|
|
1481
|
+
return e.getUint8(t);
|
|
1482
|
+
case O.UInt16:
|
|
1483
|
+
return e.getUint16(t, r);
|
|
1484
|
+
case O.UInt32:
|
|
1485
|
+
return e.getUint32(t, r);
|
|
1486
|
+
case O.UInt64:
|
|
1487
|
+
return at(e, t, r);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
function se(e, t, n) {
|
|
1491
|
+
return !(t < e.sourceOffset || e.sourceOffset + e.byteLength < t + n);
|
|
1492
|
+
}
|
|
1493
|
+
const lt = new ArrayBuffer(4), Rn = new Uint32Array(lt), zn = new Uint8Array(lt);
|
|
1494
|
+
Rn[0] = 1;
|
|
1495
|
+
const ke = zn[0] === 1;
|
|
1496
|
+
function Ze(e, t, n, r) {
|
|
1497
|
+
switch (e) {
|
|
1498
|
+
case C.Ascii:
|
|
1499
|
+
return String.fromCharCode(t.getUint8(n));
|
|
1500
|
+
case C.Undefined:
|
|
1501
|
+
case C.Uint8:
|
|
1502
|
+
return t.getUint8(n);
|
|
1503
|
+
case C.Int8:
|
|
1504
|
+
return t.getInt8(n);
|
|
1505
|
+
case C.Uint16:
|
|
1506
|
+
return t.getUint16(n, r);
|
|
1507
|
+
case C.Int16:
|
|
1508
|
+
return t.getInt16(n, r);
|
|
1509
|
+
case C.Uint32:
|
|
1510
|
+
case C.Ifd:
|
|
1511
|
+
return t.getUint32(n, r);
|
|
1512
|
+
case C.Int32:
|
|
1513
|
+
return t.getInt32(n, r);
|
|
1514
|
+
case C.Rational:
|
|
1515
|
+
return [t.getUint32(n, r), t.getUint32(n + 4, r)];
|
|
1516
|
+
case C.SignedRational:
|
|
1517
|
+
return [t.getInt32(n, r), t.getInt32(n + 4, r)];
|
|
1518
|
+
case C.Float64:
|
|
1519
|
+
return t.getFloat64(n, r);
|
|
1520
|
+
case C.Float32:
|
|
1521
|
+
return t.getFloat32(n, r);
|
|
1522
|
+
case C.Uint64:
|
|
1523
|
+
return at(t, n, r);
|
|
1524
|
+
default:
|
|
1525
|
+
throw new Error(`Unknown read type "${e}" "${C[e]}"`);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
function ct(e, t, n, r, o) {
|
|
1529
|
+
switch (o) {
|
|
1530
|
+
case C.Uint8:
|
|
1531
|
+
return new Uint8Array(t.buffer.slice(t.byteOffset + n, t.byteOffset + n + r));
|
|
1532
|
+
case C.Uint16:
|
|
1533
|
+
return e.isLittleEndian !== ke ? null : new Uint16Array(t.buffer.slice(t.byteOffset + n, t.byteOffset + n + r));
|
|
1534
|
+
case C.Uint32:
|
|
1535
|
+
return e.isLittleEndian !== ke ? null : new Uint32Array(t.buffer.slice(t.byteOffset + n, t.byteOffset + n + r));
|
|
1536
|
+
}
|
|
1537
|
+
return null;
|
|
1538
|
+
}
|
|
1539
|
+
function X(e, t, n, r, o, i) {
|
|
1540
|
+
const s = W(o), a = i * s;
|
|
1541
|
+
if (i === 1) {
|
|
1542
|
+
const c = Ze(o, n, r, e.isLittleEndian);
|
|
1543
|
+
return t && In[t] ? [c] : c;
|
|
1544
|
+
}
|
|
1545
|
+
switch (o) {
|
|
1546
|
+
case C.Ascii:
|
|
1547
|
+
return String.fromCharCode.apply(null, new Uint8Array(n.buffer, r, a - 1));
|
|
1548
|
+
}
|
|
1549
|
+
if (t === m.TileOffsets || t === m.TileByteCounts || t === m.StripOffsets || t === m.StripByteCounts) {
|
|
1550
|
+
const c = ct(e, n, r, a, o);
|
|
1551
|
+
if (c)
|
|
1552
|
+
return c;
|
|
1553
|
+
}
|
|
1554
|
+
const l = [];
|
|
1555
|
+
for (let c = 0; c < a; c += s)
|
|
1556
|
+
l.push(Ze(o, n, r + c, e.isLittleEndian));
|
|
1557
|
+
return l;
|
|
1558
|
+
}
|
|
1559
|
+
function Fn(e, t, n) {
|
|
1560
|
+
const r = t.getUint16(n + 0, e.isLittleEndian), o = t.getUint16(n + 2, e.isLittleEndian), i = K(t, n + 4, e.ifdConfig.pointer, e.isLittleEndian), a = W(o) * i;
|
|
1561
|
+
if (a <= e.ifdConfig.pointer) {
|
|
1562
|
+
const c = X(e, r, t, n + 4 + e.ifdConfig.pointer, o, i);
|
|
1563
|
+
return { type: "inline", id: r, name: m[r], count: i, value: c, dataType: o, tagOffset: n };
|
|
1564
|
+
}
|
|
1565
|
+
const l = K(t, n + 4 + e.ifdConfig.pointer, e.ifdConfig.pointer, e.isLittleEndian);
|
|
1566
|
+
switch (r) {
|
|
1567
|
+
case m.TileOffsets:
|
|
1568
|
+
case m.TileByteCounts:
|
|
1569
|
+
case m.StripByteCounts:
|
|
1570
|
+
case m.StripOffsets:
|
|
1571
|
+
const c = {
|
|
1572
|
+
type: "offset",
|
|
1573
|
+
id: r,
|
|
1574
|
+
name: m[r],
|
|
1575
|
+
count: i,
|
|
1576
|
+
dataType: o,
|
|
1577
|
+
dataOffset: l,
|
|
1578
|
+
isLoaded: !1,
|
|
1579
|
+
value: [],
|
|
1580
|
+
tagOffset: n
|
|
1581
|
+
};
|
|
1582
|
+
if (se(t, l, a)) {
|
|
1583
|
+
const u = ct(e, t, l - t.sourceOffset, a, o);
|
|
1584
|
+
u ? (c.value = u, c.isLoaded = !0) : Un(c, t);
|
|
1585
|
+
}
|
|
1586
|
+
return c;
|
|
1587
|
+
}
|
|
1588
|
+
if (se(t, l, a)) {
|
|
1589
|
+
const c = X(e, r, t, l - t.sourceOffset, o, i);
|
|
1590
|
+
return { type: "inline", id: r, name: m[r], count: i, value: c, dataType: o, tagOffset: n };
|
|
1591
|
+
}
|
|
1592
|
+
return { type: "lazy", id: r, name: m[r], count: i, dataOffset: l, dataType: o, tagOffset: n };
|
|
1593
|
+
}
|
|
1594
|
+
async function Dn(e, t, n) {
|
|
1595
|
+
if (e.value != null)
|
|
1596
|
+
return e.value;
|
|
1597
|
+
const o = W(e.dataType) * e.count, i = await t.source.fetch(e.dataOffset, o, n), s = new DataView(i);
|
|
1598
|
+
return e.value = X(t, e.id, s, 0, e.dataType, e.count), e.value;
|
|
1599
|
+
}
|
|
1600
|
+
async function Nn(e, t, n) {
|
|
1601
|
+
const r = W(t.dataType);
|
|
1602
|
+
if (t.view == null) {
|
|
1603
|
+
const o = await e.source.fetch(t.dataOffset, r * t.count, n);
|
|
1604
|
+
t.view = new DataView(o), t.view.sourceOffset = t.dataOffset;
|
|
1605
|
+
}
|
|
1606
|
+
return t.value = X(e, t.id, t.view, 0, t.dataType, t.count), t.view = void 0, t.isLoaded = !0, t.value;
|
|
1607
|
+
}
|
|
1608
|
+
function Un(e, t) {
|
|
1609
|
+
const n = W(e.dataType), r = t.byteOffset + e.dataOffset - t.sourceOffset;
|
|
1610
|
+
e.view = new DataView(t.buffer.slice(r, r + n * e.count)), e.view.sourceOffset = e.dataOffset;
|
|
1611
|
+
}
|
|
1612
|
+
async function Bn(e, t, n, r) {
|
|
1613
|
+
if (n > t.count || n < 0)
|
|
1614
|
+
throw new Error("TagOffset: out of bounds :" + n);
|
|
1615
|
+
if (t.value[n] != null)
|
|
1616
|
+
return t.value[n];
|
|
1617
|
+
const o = W(t.dataType);
|
|
1618
|
+
if (t.view == null) {
|
|
1619
|
+
const s = await e.source.fetch(t.dataOffset + n * o, o, r), a = new DataView(s), l = X(e, void 0, a, 0, t.dataType, 1);
|
|
1620
|
+
if (typeof l != "number")
|
|
1621
|
+
throw new Error("Value is not a number");
|
|
1622
|
+
return t.value[n] = l, l;
|
|
1623
|
+
}
|
|
1624
|
+
const i = X(e, void 0, t.view, n * o, t.dataType, 1);
|
|
1625
|
+
if (typeof i != "number")
|
|
1626
|
+
throw new Error("Value is not a number");
|
|
1627
|
+
return t.value[n] = i, i;
|
|
1628
|
+
}
|
|
1629
|
+
function Gn(e, t, n) {
|
|
1630
|
+
if (n > t.count || n < 0)
|
|
1631
|
+
throw new Error("TagOffset: out of bounds :" + n);
|
|
1632
|
+
if (t.value[n] != null)
|
|
1633
|
+
return t.value[n];
|
|
1634
|
+
if (t.view == null)
|
|
1635
|
+
return null;
|
|
1636
|
+
const r = W(t.dataType), o = X(e, void 0, t.view, n * r, t.dataType, 1);
|
|
1637
|
+
if (typeof o != "number")
|
|
1638
|
+
throw new Error("Value is not a number");
|
|
1639
|
+
return t.value[n] = o, o;
|
|
1640
|
+
}
|
|
1641
|
+
const Ve = 32767, Kn = /* @__PURE__ */ new Set([
|
|
1642
|
+
m.Compression,
|
|
1643
|
+
m.ImageHeight,
|
|
1644
|
+
m.ImageWidth,
|
|
1645
|
+
m.ModelPixelScale,
|
|
1646
|
+
m.ModelTiePoint,
|
|
1647
|
+
m.ModelTransformation,
|
|
1648
|
+
m.TileHeight,
|
|
1649
|
+
m.TileWidth
|
|
1650
|
+
]), _n = /* @__PURE__ */ new Set([m.GeoKeyDirectory, m.GeoAsciiParams, m.GeoDoubleParams]);
|
|
1651
|
+
class Xn {
|
|
1652
|
+
/**
|
|
1653
|
+
* Id of the tif image, generally the image index inside the tif
|
|
1654
|
+
* where 0 is the root image, and every sub image is +1
|
|
1655
|
+
*
|
|
1656
|
+
* @example 0, 1, 2
|
|
1657
|
+
*/
|
|
1658
|
+
id;
|
|
1659
|
+
/** Reference to the TIFF that owns this image */
|
|
1660
|
+
tiff;
|
|
1661
|
+
/** Has loadGeoTiffTags been called */
|
|
1662
|
+
isGeoTagsLoaded = !1;
|
|
1663
|
+
/** Sub tags stored in TiffTag.GeoKeyDirectory */
|
|
1664
|
+
tagsGeo = /* @__PURE__ */ new Map();
|
|
1665
|
+
/** All IFD tags that have been read for the image */
|
|
1666
|
+
tags;
|
|
1667
|
+
constructor(t, n, r) {
|
|
1668
|
+
this.tiff = t, this.id = n, this.tags = r;
|
|
1669
|
+
}
|
|
1670
|
+
/**
|
|
1671
|
+
* Force loading of important tags if they have not already been loaded
|
|
1672
|
+
*
|
|
1673
|
+
* @param loadGeoTags Whether to load the GeoKeyDirectory and unpack it
|
|
1674
|
+
*/
|
|
1675
|
+
async init(t = !0, n) {
|
|
1676
|
+
const r = [];
|
|
1677
|
+
Kn.forEach((o) => {
|
|
1678
|
+
r.push(this.fetch(o, n));
|
|
1679
|
+
}), t && _n.forEach((o) => {
|
|
1680
|
+
r.push(this.fetch(o, n));
|
|
1681
|
+
}), await Promise.all(r), t && await this.loadGeoTiffTags();
|
|
1682
|
+
}
|
|
1683
|
+
/**
|
|
1684
|
+
* Get the value of a TiffTag if it has been loaded, null otherwise.
|
|
1685
|
+
*
|
|
1686
|
+
* If the value is not loaded use {@link TiffImage.fetch} to load the value
|
|
1687
|
+
* Or use {@link TiffImage.has} to check if the tag exists
|
|
1688
|
+
*
|
|
1689
|
+
*
|
|
1690
|
+
* @returns value if loaded, null otherwise
|
|
1691
|
+
*/
|
|
1692
|
+
value(t) {
|
|
1693
|
+
const n = this.tags.get(t);
|
|
1694
|
+
return n == null || n.type === "offset" && n.isLoaded === !1 ? null : n.value;
|
|
1695
|
+
}
|
|
1696
|
+
/**
|
|
1697
|
+
* Does the tag exist
|
|
1698
|
+
*
|
|
1699
|
+
* @example
|
|
1700
|
+
* ```typescript
|
|
1701
|
+
* img.has(TiffTag.ImageWidth) // true
|
|
1702
|
+
* ```
|
|
1703
|
+
*
|
|
1704
|
+
* @param tag Tag to check
|
|
1705
|
+
* @returns true if the tag exists, false otherwise
|
|
1706
|
+
*/
|
|
1707
|
+
has(t) {
|
|
1708
|
+
return this.tags.has(t);
|
|
1709
|
+
}
|
|
1710
|
+
/**
|
|
1711
|
+
* Load a tag.
|
|
1712
|
+
*
|
|
1713
|
+
* If it is not currently loaded, fetch the required data for the tag.
|
|
1714
|
+
*
|
|
1715
|
+
* @example
|
|
1716
|
+
* ```typescript
|
|
1717
|
+
* await img.fetch(TiffTag.ImageWidth) // 512 (px)
|
|
1718
|
+
* ```
|
|
1719
|
+
*
|
|
1720
|
+
* @param tag tag to fetch
|
|
1721
|
+
*/
|
|
1722
|
+
async fetch(t, n) {
|
|
1723
|
+
const r = this.tags.get(t);
|
|
1724
|
+
if (r == null)
|
|
1725
|
+
return null;
|
|
1726
|
+
if (r.type === "inline")
|
|
1727
|
+
return r.value;
|
|
1728
|
+
if (r.type === "lazy")
|
|
1729
|
+
return Dn(r, this.tiff, n);
|
|
1730
|
+
if (r.isLoaded)
|
|
1731
|
+
return r.value;
|
|
1732
|
+
if (r.type === "offset")
|
|
1733
|
+
return Nn(this.tiff, r, n);
|
|
1734
|
+
throw new Error("Cannot fetch:" + t);
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Get the associated TiffTagGeo
|
|
1738
|
+
*
|
|
1739
|
+
* @example
|
|
1740
|
+
* ```typescript
|
|
1741
|
+
* image.valueGeo(TiffTagGeo.GTRasterTypeGeoKey)
|
|
1742
|
+
* ```
|
|
1743
|
+
* @throws if {@link loadGeoTiffTags} has not been called
|
|
1744
|
+
*/
|
|
1745
|
+
valueGeo(t) {
|
|
1746
|
+
if (this.isGeoTagsLoaded === !1)
|
|
1747
|
+
throw new Error("loadGeoTiffTags() has not been called");
|
|
1748
|
+
return this.tagsGeo.get(t);
|
|
1749
|
+
}
|
|
1750
|
+
/**
|
|
1751
|
+
* Load and parse the GDAL_NODATA Tifftag
|
|
1752
|
+
*
|
|
1753
|
+
* @throws if the tag is not loaded
|
|
1754
|
+
* @returns null if the tag does not exist
|
|
1755
|
+
*/
|
|
1756
|
+
get noData() {
|
|
1757
|
+
const t = this.tags.get(m.GdalNoData);
|
|
1758
|
+
if (t == null)
|
|
1759
|
+
return null;
|
|
1760
|
+
if (t.value != null)
|
|
1761
|
+
return Number(t.value);
|
|
1762
|
+
throw new Error("GdalNoData tag is not loaded");
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* Load and unpack the GeoKeyDirectory
|
|
1766
|
+
*
|
|
1767
|
+
* @see {TiffTag.GeoKeyDirectory}
|
|
1768
|
+
*/
|
|
1769
|
+
async loadGeoTiffTags() {
|
|
1770
|
+
if (this.isGeoTagsLoaded)
|
|
1771
|
+
return;
|
|
1772
|
+
const t = this.tags.get(m.GeoKeyDirectory);
|
|
1773
|
+
if (t == null) {
|
|
1774
|
+
this.isGeoTagsLoaded = !0;
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
if (t.type === "lazy" && t.value == null && await Promise.all([
|
|
1778
|
+
this.fetch(m.GeoKeyDirectory),
|
|
1779
|
+
this.fetch(m.GeoAsciiParams),
|
|
1780
|
+
this.fetch(m.GeoDoubleParams)
|
|
1781
|
+
]), this.isGeoTagsLoaded = !0, t.value == null)
|
|
1782
|
+
return;
|
|
1783
|
+
const n = t.value;
|
|
1784
|
+
if (typeof n == "number")
|
|
1785
|
+
throw new Error("Invalid geo tags found");
|
|
1786
|
+
for (let r = 4; r <= n[3] * 4; r += 4) {
|
|
1787
|
+
const o = n[r], i = n[r + 1], s = n[r + 3];
|
|
1788
|
+
if (i === 0) {
|
|
1789
|
+
this.tagsGeo.set(o, s);
|
|
1790
|
+
continue;
|
|
1791
|
+
}
|
|
1792
|
+
const a = this.tags.get(i);
|
|
1793
|
+
if (a == null || a.value == null)
|
|
1794
|
+
continue;
|
|
1795
|
+
const l = n[r + 2];
|
|
1796
|
+
if (typeof a.value == "string")
|
|
1797
|
+
this.tagsGeo.set(o, a.value.slice(s, s + l - 1).trim());
|
|
1798
|
+
else if (Array.isArray(a.value))
|
|
1799
|
+
l === 1 ? this.tagsGeo.set(o, a.value[s]) : this.tagsGeo.set(o, a.value.slice(s, s + l));
|
|
1800
|
+
else
|
|
1801
|
+
throw new Error("Failed to extract GeoTiffTags");
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
/**
|
|
1805
|
+
* Get the origin point for the image
|
|
1806
|
+
*
|
|
1807
|
+
* @returns origin point of the image
|
|
1808
|
+
*/
|
|
1809
|
+
get origin() {
|
|
1810
|
+
const t = this.value(m.ModelTiePoint);
|
|
1811
|
+
if (t != null && t.length === 6)
|
|
1812
|
+
return [t[3], t[4], t[5]];
|
|
1813
|
+
const n = this.value(m.ModelTransformation);
|
|
1814
|
+
if (n != null)
|
|
1815
|
+
return [n[3], n[7], n[11]];
|
|
1816
|
+
if (this.value(m.SubFileType) === $.ReducedImage && this.id !== 0)
|
|
1817
|
+
return this.tiff.images[0].origin;
|
|
1818
|
+
throw new Error("Image does not have a geo transformation.");
|
|
1819
|
+
}
|
|
1820
|
+
/** Is there enough geo information on this image to figure out where its actually located */
|
|
1821
|
+
get isGeoLocated() {
|
|
1822
|
+
return this.value(m.ModelPixelScale) != null || this.value(m.ModelTransformation) != null ? !0 : this.isSubImage && this.id !== 0 ? this.tiff.images[0].isGeoLocated : !1;
|
|
1823
|
+
}
|
|
1824
|
+
/**
|
|
1825
|
+
* Get the resolution of the image
|
|
1826
|
+
*
|
|
1827
|
+
* @returns [x,y,z] pixel scale
|
|
1828
|
+
*/
|
|
1829
|
+
get resolution() {
|
|
1830
|
+
const t = this.value(m.ModelPixelScale);
|
|
1831
|
+
if (t != null)
|
|
1832
|
+
return [t[0], -t[1], t[2]];
|
|
1833
|
+
const n = this.value(m.ModelTransformation);
|
|
1834
|
+
if (n != null)
|
|
1835
|
+
return [n[0], n[5], n[10]];
|
|
1836
|
+
if (this.isSubImage && this.id !== 0) {
|
|
1837
|
+
const r = this.tiff.images[0], [o, i, s] = r.resolution, a = r.size, l = this.size;
|
|
1838
|
+
return [o * a.width / l.width, i * a.height / l.height, s];
|
|
1839
|
+
}
|
|
1840
|
+
throw new Error("Image does not have a geo transformation.");
|
|
1841
|
+
}
|
|
1842
|
+
/**
|
|
1843
|
+
* Is this image a reduced size image
|
|
1844
|
+
* @see {@link TiffTag.SubFileType}
|
|
1845
|
+
* @returns true if SubFileType is Reduces image, false otherwise
|
|
1846
|
+
*/
|
|
1847
|
+
get isSubImage() {
|
|
1848
|
+
return this.value(m.SubFileType) === $.ReducedImage;
|
|
1849
|
+
}
|
|
1850
|
+
/**
|
|
1851
|
+
* Bounding box of the image
|
|
1852
|
+
*
|
|
1853
|
+
* @returns [minX, minY, maxX, maxY] bounding box
|
|
1854
|
+
*/
|
|
1855
|
+
get bbox() {
|
|
1856
|
+
const t = this.size, n = this.origin, r = this.resolution;
|
|
1857
|
+
if (n == null || t == null || r == null)
|
|
1858
|
+
throw new Error("Unable to calculate bounding box");
|
|
1859
|
+
const o = n[0], i = n[1], s = o + r[0] * t.width, a = i + r[1] * t.height;
|
|
1860
|
+
return [Math.min(o, s), Math.min(i, a), Math.max(o, s), Math.max(i, a)];
|
|
1861
|
+
}
|
|
1862
|
+
/**
|
|
1863
|
+
* Get the compression used by the tile
|
|
1864
|
+
*
|
|
1865
|
+
* @see {@link TiffCompressionMimeType}
|
|
1866
|
+
*
|
|
1867
|
+
* @returns Compression type eg webp
|
|
1868
|
+
*/
|
|
1869
|
+
get compression() {
|
|
1870
|
+
const t = this.value(m.Compression);
|
|
1871
|
+
return t == null ? null : st[t];
|
|
1872
|
+
}
|
|
1873
|
+
/**
|
|
1874
|
+
* Attempt to read the EPSG Code from TiffGeoTags
|
|
1875
|
+
*
|
|
1876
|
+
* looks at TiffTagGeo.ProjectionGeoKey, TiffTagGeo.ProjectedCRSGeoKey and TiffTagGeo.GeodeticCRSGeoKey
|
|
1877
|
+
*
|
|
1878
|
+
* @returns EPSG Code if it exists and is not user defined.
|
|
1879
|
+
*/
|
|
1880
|
+
get epsg() {
|
|
1881
|
+
const t = this.valueGeo(w.ProjectionGeoKey);
|
|
1882
|
+
if (t != null && t !== Ve)
|
|
1883
|
+
return t;
|
|
1884
|
+
let n = null;
|
|
1885
|
+
switch (this.valueGeo(w.GTModelTypeGeoKey)) {
|
|
1886
|
+
case G.Unknown:
|
|
1887
|
+
return null;
|
|
1888
|
+
case G.Projected:
|
|
1889
|
+
n = this.valueGeo(w.ProjectedCRSGeoKey);
|
|
1890
|
+
break;
|
|
1891
|
+
case G.Geographic:
|
|
1892
|
+
n = this.valueGeo(w.GeodeticCRSGeoKey);
|
|
1893
|
+
break;
|
|
1894
|
+
case G.Geocentric:
|
|
1895
|
+
n = this.valueGeo(w.GeodeticCRSGeoKey);
|
|
1896
|
+
break;
|
|
1897
|
+
case G.UserDefined:
|
|
1898
|
+
return null;
|
|
1899
|
+
}
|
|
1900
|
+
return n === Ve ? null : n;
|
|
1901
|
+
}
|
|
1902
|
+
/**
|
|
1903
|
+
* Get the size of the image
|
|
1904
|
+
*
|
|
1905
|
+
* @returns Size in pixels
|
|
1906
|
+
*/
|
|
1907
|
+
get size() {
|
|
1908
|
+
const t = this.value(m.ImageWidth), n = this.value(m.ImageHeight);
|
|
1909
|
+
if (t == null || n == null)
|
|
1910
|
+
throw new Error("Tiff has no height or width");
|
|
1911
|
+
return { width: t, height: n };
|
|
1912
|
+
}
|
|
1913
|
+
/**
|
|
1914
|
+
* Determine if this image is tiled
|
|
1915
|
+
*/
|
|
1916
|
+
isTiled() {
|
|
1917
|
+
return this.value(m.TileWidth) !== null;
|
|
1918
|
+
}
|
|
1919
|
+
/**
|
|
1920
|
+
* Get size of individual tiles
|
|
1921
|
+
*/
|
|
1922
|
+
get tileSize() {
|
|
1923
|
+
const t = this.value(m.TileWidth), n = this.value(m.TileHeight);
|
|
1924
|
+
if (t == null || n == null)
|
|
1925
|
+
throw new Error("Tiff is not tiled");
|
|
1926
|
+
return { width: t, height: n };
|
|
1927
|
+
}
|
|
1928
|
+
/**
|
|
1929
|
+
* Number of tiles used to create this image
|
|
1930
|
+
*/
|
|
1931
|
+
get tileCount() {
|
|
1932
|
+
const t = this.size, n = this.tileSize, r = Math.ceil(t.width / n.width), o = Math.ceil(t.height / n.height);
|
|
1933
|
+
return { x: r, y: o };
|
|
1934
|
+
}
|
|
1935
|
+
/**
|
|
1936
|
+
* Get the pointer to where the tiles start in the Tiff file
|
|
1937
|
+
*
|
|
1938
|
+
* @remarks Used to read tiled tiffs
|
|
1939
|
+
*
|
|
1940
|
+
* @returns file offset to where the tiffs are stored
|
|
1941
|
+
*/
|
|
1942
|
+
get tileOffset() {
|
|
1943
|
+
const t = this.tags.get(m.TileOffsets);
|
|
1944
|
+
if (t == null)
|
|
1945
|
+
throw new Error("No tile offsets found");
|
|
1946
|
+
return t;
|
|
1947
|
+
}
|
|
1948
|
+
/**
|
|
1949
|
+
* Get the number of strip's inside this tiff
|
|
1950
|
+
*
|
|
1951
|
+
* @remarks Used to read striped tiffs
|
|
1952
|
+
*
|
|
1953
|
+
* @returns number of strips present
|
|
1954
|
+
*/
|
|
1955
|
+
get stripCount() {
|
|
1956
|
+
return this.tags.get(m.StripByteCounts)?.count ?? 0;
|
|
1957
|
+
}
|
|
1958
|
+
// Clamp the bounds of the output image to the size of the image, as sometimes the edge tiles are not full tiles
|
|
1959
|
+
getTileBounds(t, n) {
|
|
1960
|
+
const { size: r, tileSize: o } = this, i = n * o.height, s = t * o.width, a = s + o.width >= r.width ? r.width - s : o.width, l = i + o.height >= r.height ? r.height - i : o.height;
|
|
1961
|
+
return { x: s, y: i, width: a, height: l };
|
|
1962
|
+
}
|
|
1963
|
+
/**
|
|
1964
|
+
* Read a strip into a ArrayBuffer
|
|
1965
|
+
*
|
|
1966
|
+
* Image has to be striped see {@link stripCount}
|
|
1967
|
+
*
|
|
1968
|
+
* @param index Strip index to read
|
|
1969
|
+
*/
|
|
1970
|
+
async getStrip(t, n) {
|
|
1971
|
+
if (this.isTiled())
|
|
1972
|
+
throw new Error("Cannot read stripes, tiff is tiled: " + t);
|
|
1973
|
+
const r = this.tags.get(m.StripByteCounts), o = this.tags.get(m.StripOffsets);
|
|
1974
|
+
if (t >= r.count)
|
|
1975
|
+
throw new Error("Cannot read strip, index out of bounds");
|
|
1976
|
+
const [i, s] = await Promise.all([
|
|
1977
|
+
Q(this.tiff, o, t, n),
|
|
1978
|
+
Q(this.tiff, r, t, n)
|
|
1979
|
+
]);
|
|
1980
|
+
return this.getBytes(i, s, n);
|
|
1981
|
+
}
|
|
1982
|
+
/** The jpeg header is stored in the IFD, read the JPEG header and adjust the byte array to include it */
|
|
1983
|
+
getJpegHeader(t) {
|
|
1984
|
+
const n = this.value(m.JpegTables);
|
|
1985
|
+
if (n == null)
|
|
1986
|
+
throw new Error("Unable to find Jpeg header");
|
|
1987
|
+
const r = n.slice(0, n.length - 2), o = new Uint8Array(t.byteLength + r.length - 2);
|
|
1988
|
+
return o.set(r, 0), o.set(new Uint8Array(t).slice(2), r.length), o.buffer.slice(o.byteOffset, o.byteOffset + o.byteLength);
|
|
1989
|
+
}
|
|
1990
|
+
/** Read image bytes at the given offset */
|
|
1991
|
+
async getBytes(t, n, r) {
|
|
1992
|
+
if (n === 0)
|
|
1993
|
+
return null;
|
|
1994
|
+
const o = await this.tiff.source.fetch(t, n, r);
|
|
1995
|
+
if (o.byteLength < n)
|
|
1996
|
+
throw new Error(`Failed to fetch bytes from offset:${t} wanted:${n} got:${o.byteLength}`);
|
|
1997
|
+
let i = this.value(m.Compression);
|
|
1998
|
+
i == null && (i = P.None);
|
|
1999
|
+
const s = Mn(i) ?? x.None;
|
|
2000
|
+
return i === P.Jpeg ? { mimeType: s, bytes: this.getJpegHeader(o), compression: i } : { mimeType: s, bytes: o, compression: i };
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Load a tile into a ArrayBuffer
|
|
2004
|
+
*
|
|
2005
|
+
* if the tile compression is JPEG, This will also apply the JPEG compression tables to the resulting ArrayBuffer see {@link getJpegHeader}
|
|
2006
|
+
*
|
|
2007
|
+
* @param x Tile x offset
|
|
2008
|
+
* @param y Tile y offset
|
|
2009
|
+
*/
|
|
2010
|
+
async getTile(t, n, r) {
|
|
2011
|
+
const o = this.size, i = this.tileSize;
|
|
2012
|
+
if (i == null)
|
|
2013
|
+
throw new Error("Tiff is not tiled");
|
|
2014
|
+
const s = Math.ceil(o.height / i.height), a = Math.ceil(o.width / i.width);
|
|
2015
|
+
if (t >= a || n >= s)
|
|
2016
|
+
throw new Error(`Tile index is outside of range x:${t} >= ${a} or y:${n} >= ${s}`);
|
|
2017
|
+
const l = n * a + t, c = a * s;
|
|
2018
|
+
if (l >= c)
|
|
2019
|
+
throw new Error(`Tile index is outside of tile range: ${l} >= ${c}`);
|
|
2020
|
+
const { offset: u, imageSize: h } = await this.getTileSize(l, r);
|
|
2021
|
+
return this.getBytes(u, h, r);
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Does this tile exist in the tiff and does it actually have a value
|
|
2025
|
+
*
|
|
2026
|
+
* Sparse tiffs can have a lot of empty tiles, they set the tile size to `0 bytes` when the tile is empty
|
|
2027
|
+
* this checks the tile byte size to validate if it actually has any data.
|
|
2028
|
+
*
|
|
2029
|
+
* @param x Tile x offset
|
|
2030
|
+
* @param y Tile y offset
|
|
2031
|
+
*
|
|
2032
|
+
* @returns if the tile exists and has data
|
|
2033
|
+
*/
|
|
2034
|
+
async hasTile(t, n, r) {
|
|
2035
|
+
const o = this.tileSize, i = this.size;
|
|
2036
|
+
if (o == null)
|
|
2037
|
+
throw new Error("Tiff is not tiled");
|
|
2038
|
+
const s = Math.ceil(i.height / o.height), a = Math.ceil(i.width / o.width);
|
|
2039
|
+
if (t >= a || n >= s)
|
|
2040
|
+
return !1;
|
|
2041
|
+
const l = n * a + t;
|
|
2042
|
+
return (await this.getTileSize(l, r)).offset > 0;
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* Load the offset and byteCount of a tile
|
|
2046
|
+
*
|
|
2047
|
+
* if the tiff is sparse, offset and byteCount will be zero if the tile is empty
|
|
2048
|
+
*
|
|
2049
|
+
* @param index index in the tile array
|
|
2050
|
+
* @returns Offset and byteCount for the tile
|
|
2051
|
+
*/
|
|
2052
|
+
async getTileSize(t, n) {
|
|
2053
|
+
const r = this.tags.get(m.TileByteCounts), o = Pe(this.tiff, this.tileOffset, t), i = Pe(this.tiff, r, t);
|
|
2054
|
+
if (o != null && i != null)
|
|
2055
|
+
return { offset: o, imageSize: i };
|
|
2056
|
+
const s = this.tiff.options?.tileLeaderByteSize;
|
|
2057
|
+
if (s) {
|
|
2058
|
+
const c = o ?? await Q(this.tiff, this.tileOffset, t, n);
|
|
2059
|
+
if (c === 0)
|
|
2060
|
+
return { offset: 0, imageSize: 0 };
|
|
2061
|
+
const u = await this.tiff.source.fetch(c - s, s, n);
|
|
2062
|
+
return { offset: c, imageSize: K(new DataView(u), 0, s, this.tiff.isLittleEndian) };
|
|
2063
|
+
}
|
|
2064
|
+
if (r == null)
|
|
2065
|
+
throw new Error("No tile byte counts found");
|
|
2066
|
+
const [a, l] = await Promise.all([
|
|
2067
|
+
o ?? Q(this.tiff, this.tileOffset, t, n),
|
|
2068
|
+
i ?? Q(this.tiff, r, t, n)
|
|
2069
|
+
]);
|
|
2070
|
+
return { offset: a, imageSize: l };
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
function Q(e, t, n, r) {
|
|
2074
|
+
const o = Pe(e, t, n);
|
|
2075
|
+
return o != null ? Promise.resolve(o) : Bn(e, t, n, r);
|
|
2076
|
+
}
|
|
2077
|
+
function Pe(e, t, n) {
|
|
2078
|
+
if (n < 0)
|
|
2079
|
+
throw new Error(`Tiff: ${e.source.url.href} out of bounds ${m[t.id]} index:${n} total:${t.count}`);
|
|
2080
|
+
return n >= t.count ? 0 : t.type === "inline" || t.isLoaded ? t.value[n] : Gn(e, t, n);
|
|
2081
|
+
}
|
|
2082
|
+
var k;
|
|
2083
|
+
(function(e) {
|
|
2084
|
+
e.GdalStructuralMetadataSize = "GDAL_STRUCTURAL_METADATA_SIZE", e.Layout = "LAYOUT", e.BlockOrder = "BLOCK_ORDER", e.BlockLeader = "BLOCK_LEADER", e.BlockTrailer = "BLOCK_TRAILER", e.KnownIncompatibleEdition = "KNOWN_INCOMPATIBLE_EDITION", e.MaskInterleavedWithImagery = "MASK_INTERLEAVED_WITH_IMAGERY";
|
|
2085
|
+
})(k || (k = {}));
|
|
2086
|
+
var Ye;
|
|
2087
|
+
(function(e) {
|
|
2088
|
+
e.RowMajor = "ROW_MAJOR";
|
|
2089
|
+
})(Ye || (Ye = {}));
|
|
2090
|
+
var be;
|
|
2091
|
+
(function(e) {
|
|
2092
|
+
e.uint32 = "SIZE_AS_UINT4";
|
|
2093
|
+
})(be || (be = {}));
|
|
2094
|
+
class Wn {
|
|
2095
|
+
options = /* @__PURE__ */ new Map();
|
|
2096
|
+
/**
|
|
2097
|
+
* Has GDAL optimized this tiff
|
|
2098
|
+
*/
|
|
2099
|
+
get isCogOptimized() {
|
|
2100
|
+
return this.isBroken ? !1 : this.options.get(k.Layout) === "IFDS_BEFORE_DATA";
|
|
2101
|
+
}
|
|
2102
|
+
/**
|
|
2103
|
+
* Has GDAL determined this tiff is now broken
|
|
2104
|
+
*/
|
|
2105
|
+
get isBroken() {
|
|
2106
|
+
return this.options.get(k.KnownIncompatibleEdition) === "YES";
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* Load the ghost options from a source
|
|
2110
|
+
* @param bytes the ghost header bytes
|
|
2111
|
+
*/
|
|
2112
|
+
process(t, n, r) {
|
|
2113
|
+
let o = "", i = "", s = !1;
|
|
2114
|
+
for (let a = 0; a < r; a++) {
|
|
2115
|
+
const l = t.getUint8(n + a);
|
|
2116
|
+
if (l === 0)
|
|
2117
|
+
break;
|
|
2118
|
+
const c = String.fromCharCode(l);
|
|
2119
|
+
c === `
|
|
2120
|
+
` ? (this.options.set(o.trim(), i.trim()), o = "", i = "", s = !1) : c === "=" ? s = !0 : s ? i += c : o += c;
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
/**
|
|
2124
|
+
* If the tile leader is set, how many bytes are allocated to the tile size
|
|
2125
|
+
*/
|
|
2126
|
+
get tileLeaderByteSize() {
|
|
2127
|
+
switch (this.options.get(k.BlockLeader)) {
|
|
2128
|
+
case be.uint32:
|
|
2129
|
+
return O.UInt32;
|
|
2130
|
+
default:
|
|
2131
|
+
return null;
|
|
2132
|
+
}
|
|
2133
|
+
}
|
|
2134
|
+
get isMaskInterleaved() {
|
|
2135
|
+
return this.options.get(k.MaskInterleavedWithImagery) === "YES";
|
|
2136
|
+
}
|
|
2137
|
+
}
|
|
2138
|
+
const ut = {
|
|
2139
|
+
version: N.Tiff,
|
|
2140
|
+
pointer: O.UInt32,
|
|
2141
|
+
offset: O.UInt16,
|
|
2142
|
+
/**
|
|
2143
|
+
* Each tag entry is specified as
|
|
2144
|
+
* UInt16:TagCode
|
|
2145
|
+
* UInt16:TagType
|
|
2146
|
+
* UInt32:TagCount
|
|
2147
|
+
* UInt32:Pointer To Value or value
|
|
2148
|
+
*/
|
|
2149
|
+
ifd: O.UInt16 + O.UInt16 + 2 * O.UInt32
|
|
2150
|
+
}, ht = {
|
|
2151
|
+
version: N.BigTiff,
|
|
2152
|
+
/** Size of most pointers */
|
|
2153
|
+
pointer: O.UInt64,
|
|
2154
|
+
/** Size of offsets */
|
|
2155
|
+
offset: O.UInt64,
|
|
2156
|
+
/**
|
|
2157
|
+
* Each tag entry is specified as
|
|
2158
|
+
* UInt16:TagCode
|
|
2159
|
+
* UInt16:TagType
|
|
2160
|
+
* UInt64:TagCount
|
|
2161
|
+
* UInt64:Pointer To Value or value
|
|
2162
|
+
*/
|
|
2163
|
+
ifd: O.UInt16 + O.UInt16 + 2 * O.UInt64
|
|
2164
|
+
};
|
|
2165
|
+
N.BigTiff + "", N.Tiff + "";
|
|
2166
|
+
function Hn(e, t = 4, n = !0) {
|
|
2167
|
+
const r = e.toString(16).padStart(t, "0");
|
|
2168
|
+
return n ? "0x" + r : r;
|
|
2169
|
+
}
|
|
2170
|
+
class Z {
|
|
2171
|
+
/** Read 16KB blocks at a time */
|
|
2172
|
+
static DefaultReadSize = 16 * 1024;
|
|
2173
|
+
/** Read 16KB blocks at a time */
|
|
2174
|
+
defaultReadSize = Z.DefaultReadSize;
|
|
2175
|
+
/** Where this cog is fetching its data from */
|
|
2176
|
+
source;
|
|
2177
|
+
/** Big or small Tiff */
|
|
2178
|
+
version = N.Tiff;
|
|
2179
|
+
/** List of images, o is the base image */
|
|
2180
|
+
images = [];
|
|
2181
|
+
/** Ghost header options */
|
|
2182
|
+
options;
|
|
2183
|
+
/** Configuration for the size of the IFD */
|
|
2184
|
+
ifdConfig = ut;
|
|
2185
|
+
/** Is the tiff being read is little Endian */
|
|
2186
|
+
isLittleEndian = !1;
|
|
2187
|
+
/** Has init() been called */
|
|
2188
|
+
isInitialized = !1;
|
|
2189
|
+
_initPromise;
|
|
2190
|
+
/** A Tiff constructed from a source will not be pre-initialized with {@link init}. */
|
|
2191
|
+
constructor(t, n = { defaultReadSize: Z.DefaultReadSize }) {
|
|
2192
|
+
this.source = t, this.defaultReadSize = n.defaultReadSize;
|
|
2193
|
+
}
|
|
2194
|
+
/** Create a tiff and initialize it by reading the tiff headers */
|
|
2195
|
+
static create(t, n = { defaultReadSize: Z.DefaultReadSize }) {
|
|
2196
|
+
return new Z(t, n).init(n);
|
|
2197
|
+
}
|
|
2198
|
+
/**
|
|
2199
|
+
* Initialize the tiff loading in the header and all image headers.
|
|
2200
|
+
*
|
|
2201
|
+
* This is only required if the Tiff was created with the constructor, if you
|
|
2202
|
+
* used {@link create} this will have already been called.
|
|
2203
|
+
*/
|
|
2204
|
+
init(t) {
|
|
2205
|
+
return this.isInitialized ? Promise.resolve(this) : this._initPromise ? this._initPromise : (this._initPromise = this.readHeader(t), this._initPromise);
|
|
2206
|
+
}
|
|
2207
|
+
/**
|
|
2208
|
+
* Find a image which has a resolution similar to the provided resolution
|
|
2209
|
+
*
|
|
2210
|
+
* @param resolution resolution to find
|
|
2211
|
+
*/
|
|
2212
|
+
getImageByResolution(t) {
|
|
2213
|
+
const n = this.images[0], r = n.size, [o] = n.resolution, i = o * r.width;
|
|
2214
|
+
for (let s = this.images.length - 1; s > 0; s--) {
|
|
2215
|
+
const a = this.images[s], l = a.size;
|
|
2216
|
+
if (i / l.width - t <= 0.01)
|
|
2217
|
+
return a;
|
|
2218
|
+
}
|
|
2219
|
+
return n;
|
|
2220
|
+
}
|
|
2221
|
+
/** Read the Starting header and all Image headers from the source */
|
|
2222
|
+
async readHeader(t) {
|
|
2223
|
+
if (this.isInitialized)
|
|
2224
|
+
return this;
|
|
2225
|
+
const n = new DataView(await this.source.fetch(0, Je(this.source, 0, this.defaultReadSize), t));
|
|
2226
|
+
if (n.byteLength === 0)
|
|
2227
|
+
throw new Error("Unable to read empty tiff");
|
|
2228
|
+
n.sourceOffset = 0;
|
|
2229
|
+
let r = 0;
|
|
2230
|
+
const o = n.getUint16(r, this.isLittleEndian);
|
|
2231
|
+
r += 2, this.isLittleEndian = o === ye.Little, this.version = n.getUint16(r, this.isLittleEndian), r += 2;
|
|
2232
|
+
let i;
|
|
2233
|
+
if (this.version === N.BigTiff) {
|
|
2234
|
+
this.ifdConfig = ht;
|
|
2235
|
+
const a = n.getUint16(r, this.isLittleEndian);
|
|
2236
|
+
if (r += 2, a !== 8)
|
|
2237
|
+
throw new Error("Only 8byte pointers are supported");
|
|
2238
|
+
const l = n.getUint16(r, this.isLittleEndian);
|
|
2239
|
+
if (r += 2, l !== 0)
|
|
2240
|
+
throw new Error("Invalid big tiff header");
|
|
2241
|
+
i = K(n, r, this.ifdConfig.pointer, this.isLittleEndian), r += this.ifdConfig.pointer;
|
|
2242
|
+
} else if (this.version === N.Tiff)
|
|
2243
|
+
i = K(n, r, this.ifdConfig.pointer, this.isLittleEndian), r += this.ifdConfig.pointer;
|
|
2244
|
+
else
|
|
2245
|
+
throw new Error(`Only tiff supported version:${String(this.version)}`);
|
|
2246
|
+
const s = i - r;
|
|
2247
|
+
for (s > 0 && s < 16 * 1024 && (this.options = new Wn(), this.options.process(n, r, s)); i !== 0; ) {
|
|
2248
|
+
let a = n;
|
|
2249
|
+
if (!se(a, i, 1024)) {
|
|
2250
|
+
const l = await this.source.fetch(i, Je(this.source, i, this.defaultReadSize), t);
|
|
2251
|
+
a = new DataView(l), a.sourceOffset = i;
|
|
2252
|
+
}
|
|
2253
|
+
i = this.readIfd(i, a);
|
|
2254
|
+
}
|
|
2255
|
+
return await Promise.all(this.images.map((a) => a.init(!0, t))), this.isInitialized = !0, this;
|
|
2256
|
+
}
|
|
2257
|
+
/**
|
|
2258
|
+
* Read a IFD at a the provided offset
|
|
2259
|
+
*
|
|
2260
|
+
* @param offset file offset to read the header from
|
|
2261
|
+
* @param view offset that contains the bytes for the header
|
|
2262
|
+
*/
|
|
2263
|
+
readIfd(t, n) {
|
|
2264
|
+
const r = t - n.sourceOffset, o = K(n, r, this.ifdConfig.offset, this.isLittleEndian), i = /* @__PURE__ */ new Map(), s = o * this.ifdConfig.ifd;
|
|
2265
|
+
if (!se(n, t, s))
|
|
2266
|
+
throw new Error("IFD out of range @ " + Hn(t) + " IFD" + this.images.length);
|
|
2267
|
+
const a = this.ifdConfig.ifd, l = r + this.ifdConfig.offset;
|
|
2268
|
+
for (let c = 0; c < o; c++) {
|
|
2269
|
+
const u = Fn(this, n, l + c * a);
|
|
2270
|
+
i.set(u.id, u);
|
|
2271
|
+
}
|
|
2272
|
+
return this.images.push(new Xn(this, this.images.length, i)), K(n, l + o * a, this.ifdConfig.pointer, this.isLittleEndian);
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
function Je(e, t, n) {
|
|
2276
|
+
const r = e.metadata?.size;
|
|
2277
|
+
return r == null || r < 0 ? n : t + n > r ? r - t : n;
|
|
2278
|
+
}
|
|
2279
|
+
async function Ce(e, t) {
|
|
2280
|
+
const n = new Blob([e]), r = await createImageBitmap(n), o = new OffscreenCanvas(r.width, r.height), i = o.getContext("2d");
|
|
2281
|
+
i.drawImage(r, 0, 0), r.close();
|
|
2282
|
+
const { width: s, height: a } = o, c = i.getImageData(0, 0, s, a).data, u = t.samplesPerPixel;
|
|
2283
|
+
if (u === 4)
|
|
2284
|
+
return { layout: "pixel-interleaved", data: c };
|
|
2285
|
+
if (u === 3) {
|
|
2286
|
+
const h = s * a, p = new Uint8ClampedArray(h * 3);
|
|
2287
|
+
for (let d = 0, g = 0; d < p.length; d += 3, g += 4)
|
|
2288
|
+
p[d] = c[g], p[d + 1] = c[g + 1], p[d + 2] = c[g + 2];
|
|
2289
|
+
return { layout: "pixel-interleaved", data: p };
|
|
2290
|
+
}
|
|
2291
|
+
if (u === 1) {
|
|
2292
|
+
const h = s * a, p = new Uint8ClampedArray(h);
|
|
2293
|
+
for (let d = 0, g = 0; d < h; d++, g += 4)
|
|
2294
|
+
p[d] = c[g];
|
|
2295
|
+
return { layout: "pixel-interleaved", data: p };
|
|
2296
|
+
}
|
|
2297
|
+
throw new Error(`Unsupported SamplesPerPixel for JPEG: ${u}`);
|
|
2298
|
+
}
|
|
2299
|
+
function kn(e, t = "") {
|
|
2300
|
+
if (!e)
|
|
2301
|
+
throw new Error(t);
|
|
2302
|
+
}
|
|
2303
|
+
async function Zn(e, { format: t, signal: n }) {
|
|
2304
|
+
const r = e instanceof Response ? e : new Response(e);
|
|
2305
|
+
kn(r.body, "Response does not contain body.");
|
|
2306
|
+
try {
|
|
2307
|
+
return await new Response(r.body.pipeThrough(new DecompressionStream(t), { signal: n })).arrayBuffer();
|
|
2308
|
+
} catch {
|
|
2309
|
+
throw n?.throwIfAborted(), new Error(`Failed to decode ${t}`);
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
async function dt(e) {
|
|
2313
|
+
return Zn(e, { format: "deflate" });
|
|
2314
|
+
}
|
|
2315
|
+
function Vn(e, t) {
|
|
2316
|
+
const n = e;
|
|
2317
|
+
let r = 0, o = e.length - t;
|
|
2318
|
+
do {
|
|
2319
|
+
for (let i = t; i > 0; i--)
|
|
2320
|
+
n[r + t] = (n[r + t] ?? 0) + (n[r] ?? 0), r++;
|
|
2321
|
+
o -= t;
|
|
2322
|
+
} while (o > 0);
|
|
2323
|
+
}
|
|
2324
|
+
function Yn(e, t, n) {
|
|
2325
|
+
let r = 0, o = e.length;
|
|
2326
|
+
const i = o / n;
|
|
2327
|
+
for (; o > t; ) {
|
|
2328
|
+
for (let a = t; a > 0; a--)
|
|
2329
|
+
e[r + t] += e[r], r++;
|
|
2330
|
+
o -= t;
|
|
2331
|
+
}
|
|
2332
|
+
const s = e.slice();
|
|
2333
|
+
for (let a = 0; a < i; a++)
|
|
2334
|
+
for (let l = 0; l < n; l++)
|
|
2335
|
+
e[n * a + l] = s[(n - l - 1) * i + a];
|
|
2336
|
+
}
|
|
2337
|
+
function Jn(e, t, n, r, o, i, s) {
|
|
2338
|
+
if (t === V.None)
|
|
2339
|
+
return e;
|
|
2340
|
+
const a = o / 8, l = s === U.Separate ? 1 : i;
|
|
2341
|
+
for (let c = 0; c < r; c++) {
|
|
2342
|
+
const u = c * l * n * a;
|
|
2343
|
+
if (u >= e.byteLength)
|
|
2344
|
+
break;
|
|
2345
|
+
if (t === V.Horizontal) {
|
|
2346
|
+
let h;
|
|
2347
|
+
const p = l * n;
|
|
2348
|
+
switch (o) {
|
|
2349
|
+
case 8:
|
|
2350
|
+
h = new Uint8Array(e, u, p);
|
|
2351
|
+
break;
|
|
2352
|
+
case 16:
|
|
2353
|
+
h = new Uint16Array(e, u, p);
|
|
2354
|
+
break;
|
|
2355
|
+
case 32:
|
|
2356
|
+
h = new Uint32Array(e, u, p);
|
|
2357
|
+
break;
|
|
2358
|
+
default:
|
|
2359
|
+
throw new Error(`Predictor 2 not supported for ${o} bits per sample.`);
|
|
2360
|
+
}
|
|
2361
|
+
Vn(h, l);
|
|
2362
|
+
} else if (t === V.FloatingPoint) {
|
|
2363
|
+
const h = new Uint8Array(e, u, l * n * a);
|
|
2364
|
+
Yn(h, l, a);
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
return e;
|
|
2368
|
+
}
|
|
2369
|
+
async function qn(e) {
|
|
2370
|
+
return e;
|
|
2371
|
+
}
|
|
2372
|
+
const D = /* @__PURE__ */ new Map();
|
|
2373
|
+
D.set(P.None, () => Promise.resolve(qn));
|
|
2374
|
+
D.set(P.Deflate, () => Promise.resolve(dt));
|
|
2375
|
+
D.set(P.DeflateOther, () => Promise.resolve(dt));
|
|
2376
|
+
D.set(P.Lzw, () => import("./lzw-BY5a_5nb.js").then((e) => e.decode));
|
|
2377
|
+
D.set(P.Zstd, () => import("./zstd-jXobGRcq.js").then((e) => e.decode));
|
|
2378
|
+
D.set(P.Jpeg, () => Promise.resolve(Ce));
|
|
2379
|
+
D.set(P.Jpeg6, () => Promise.resolve(Ce));
|
|
2380
|
+
D.set(P.Webp, () => Promise.resolve(Ce));
|
|
2381
|
+
D.set(P.Lerc, () => import("./lerc-BhtFlCQ3.js").then((e) => e.l).then((e) => e.decode));
|
|
2382
|
+
async function je(e, t, n) {
|
|
2383
|
+
const r = D.get(t);
|
|
2384
|
+
if (!r)
|
|
2385
|
+
throw new Error(`Unsupported compression: ${t}`);
|
|
2386
|
+
const i = await (await r())(e, n);
|
|
2387
|
+
if (i instanceof ArrayBuffer) {
|
|
2388
|
+
const { predictor: s, width: a, height: l, bitsPerSample: c, samplesPerPixel: u, planarConfiguration: h } = n, p = Jn(i, s, a, l, c, u, h);
|
|
2389
|
+
return {
|
|
2390
|
+
layout: "pixel-interleaved",
|
|
2391
|
+
data: Tn(p, n)
|
|
2392
|
+
};
|
|
2393
|
+
}
|
|
2394
|
+
return i;
|
|
2395
|
+
}
|
|
2396
|
+
function Qn(e, t) {
|
|
2397
|
+
const n = new Uint8Array(e), r = new Uint8Array(t);
|
|
2398
|
+
for (let o = 0; o < t; o++)
|
|
2399
|
+
r[o] = n[o >> 3] >> 7 - (o & 7) & 1 ? 255 : 0;
|
|
2400
|
+
return r;
|
|
2401
|
+
}
|
|
2402
|
+
function Tn(e, t) {
|
|
2403
|
+
const { sampleFormat: n, bitsPerSample: r } = t;
|
|
2404
|
+
switch (n) {
|
|
2405
|
+
case F.Uint:
|
|
2406
|
+
switch (r) {
|
|
2407
|
+
case 1:
|
|
2408
|
+
return Qn(e, t.width * t.height * t.samplesPerPixel);
|
|
2409
|
+
case 8:
|
|
2410
|
+
return new Uint8Array(e);
|
|
2411
|
+
case 16:
|
|
2412
|
+
return new Uint16Array(e);
|
|
2413
|
+
case 32:
|
|
2414
|
+
return new Uint32Array(e);
|
|
2415
|
+
}
|
|
2416
|
+
break;
|
|
2417
|
+
case F.Int:
|
|
2418
|
+
switch (r) {
|
|
2419
|
+
case 8:
|
|
2420
|
+
return new Int8Array(e);
|
|
2421
|
+
case 16:
|
|
2422
|
+
return new Int16Array(e);
|
|
2423
|
+
case 32:
|
|
2424
|
+
return new Int32Array(e);
|
|
2425
|
+
}
|
|
2426
|
+
break;
|
|
2427
|
+
case F.Float:
|
|
2428
|
+
switch (r) {
|
|
2429
|
+
case 32:
|
|
2430
|
+
return new Float32Array(e);
|
|
2431
|
+
case 64:
|
|
2432
|
+
return new Float64Array(e);
|
|
2433
|
+
}
|
|
2434
|
+
break;
|
|
2435
|
+
}
|
|
2436
|
+
throw new Error(`Unsupported sample format/depth: SampleFormat=${n}, BitsPerSample=${r}`);
|
|
2437
|
+
}
|
|
2438
|
+
class $n {
|
|
2439
|
+
name = "source:cache";
|
|
2440
|
+
maxSize;
|
|
2441
|
+
/** Number of bytes cached in cacheA, when this overflows maxSize cacheA is moved to cacheB and cacheB is dropped */
|
|
2442
|
+
size = 0;
|
|
2443
|
+
/** Number of times `this.cacheB` has been cleared */
|
|
2444
|
+
resets = 0;
|
|
2445
|
+
/** Primary cache of objects */
|
|
2446
|
+
cacheA = /* @__PURE__ */ new Map();
|
|
2447
|
+
cacheB = /* @__PURE__ */ new Map();
|
|
2448
|
+
/** List of protocols to cache */
|
|
2449
|
+
protocols;
|
|
2450
|
+
constructor(t) {
|
|
2451
|
+
this.maxSize = t.size, this.protocols = new Set(t.protocols ?? []);
|
|
2452
|
+
}
|
|
2453
|
+
fetch(t, n) {
|
|
2454
|
+
if (this.protocols.size > 0 && !this.protocols.has(t.source.url.protocol) || t.length == null)
|
|
2455
|
+
return n(t);
|
|
2456
|
+
const r = `${t.source.url.toString()}@${t.offset}+${t.length}`;
|
|
2457
|
+
let o = this.cacheA.get(r);
|
|
2458
|
+
return o ? (o.hits++, o.promise) : (o = this.cacheB.get(r), o ? (o.hits++, o.saves++, this.size += o.size, this.cacheA.set(r, o), o.promise) : (o = { promise: n(t), hits: 0, saves: 0, size: t.length }, this.size += o.size, this.size > this.maxSize && (this.size = o.size, this.cacheB = this.cacheA, this.cacheA = /* @__PURE__ */ new Map(), this.resets++), this.cacheA.set(r, o), o.promise));
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
class B extends Error {
|
|
2462
|
+
/** Status code for the error eg 403 - Forbidden vs 404 Not found */
|
|
2463
|
+
code;
|
|
2464
|
+
/** URL that the status code came from */
|
|
2465
|
+
url;
|
|
2466
|
+
/** File system that triggered the error */
|
|
2467
|
+
source;
|
|
2468
|
+
constructor(t, n, r, o) {
|
|
2469
|
+
super(t, { cause: o }), this.code = n, this.url = r.url, this.source = r, Object.defineProperty(this, "_sourceError", {
|
|
2470
|
+
enumerable: !1,
|
|
2471
|
+
// hide it from for..in
|
|
2472
|
+
value: "SourceError"
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2475
|
+
/** Check that a unknown is a FsError */
|
|
2476
|
+
static is(t) {
|
|
2477
|
+
return t instanceof B ? !0 : typeof t != "object" || t == null ? !1 : "_sourceError" in t && t._sourceError === "SourceError";
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
const le = {
|
|
2481
|
+
/** Convert a offset/length to a range request
|
|
2482
|
+
*
|
|
2483
|
+
* @example
|
|
2484
|
+
* ```typescript
|
|
2485
|
+
* ContentRange.toRange(10) // "bytes=10"
|
|
2486
|
+
* ContentRange.toRange(0, 1024) // "bytes=0-1023"
|
|
2487
|
+
* ```
|
|
2488
|
+
*/
|
|
2489
|
+
toRange(e, t) {
|
|
2490
|
+
if (t == null)
|
|
2491
|
+
return `bytes=${e}`;
|
|
2492
|
+
if (e < 0)
|
|
2493
|
+
throw new Error("Cannot read from remote source with negative offset and length");
|
|
2494
|
+
return `bytes=${e}-${e + t - 1}`;
|
|
2495
|
+
},
|
|
2496
|
+
/**
|
|
2497
|
+
* Parse a Content-Range header to extract the size of the source
|
|
2498
|
+
*
|
|
2499
|
+
* @example
|
|
2500
|
+
* ```typescript
|
|
2501
|
+
* ContentRange.parseRange("bytes 200-1000/67589"); // 67589
|
|
2502
|
+
* ```
|
|
2503
|
+
* @throws if range is not a Content-Range with size
|
|
2504
|
+
*/
|
|
2505
|
+
parseSize(e) {
|
|
2506
|
+
const [t, n] = e.split(" ");
|
|
2507
|
+
if (t !== "bytes")
|
|
2508
|
+
throw new Error("Failed to parse content-range: " + e);
|
|
2509
|
+
if (n == null)
|
|
2510
|
+
throw new Error("Failed to parse content-range: " + e);
|
|
2511
|
+
const [, r] = n.split("/"), o = Number(r);
|
|
2512
|
+
if (isNaN(o))
|
|
2513
|
+
throw new Error("Failed to parse content-range: " + e);
|
|
2514
|
+
return o;
|
|
2515
|
+
}
|
|
2516
|
+
};
|
|
2517
|
+
class er {
|
|
2518
|
+
source;
|
|
2519
|
+
middleware;
|
|
2520
|
+
static is(t) {
|
|
2521
|
+
return "middleware" in t;
|
|
2522
|
+
}
|
|
2523
|
+
constructor(t, n = []) {
|
|
2524
|
+
this.source = t, this.middleware = n;
|
|
2525
|
+
}
|
|
2526
|
+
get type() {
|
|
2527
|
+
return this.source.type;
|
|
2528
|
+
}
|
|
2529
|
+
get url() {
|
|
2530
|
+
return this.source.url;
|
|
2531
|
+
}
|
|
2532
|
+
get metadata() {
|
|
2533
|
+
return this.source.metadata;
|
|
2534
|
+
}
|
|
2535
|
+
head(t) {
|
|
2536
|
+
return this.source.head(t);
|
|
2537
|
+
}
|
|
2538
|
+
async fetch(t, n, r) {
|
|
2539
|
+
const o = this.middleware;
|
|
2540
|
+
if (o == null || o.length === 0)
|
|
2541
|
+
return this.source.fetch(t, n, r);
|
|
2542
|
+
const i = (s) => this.source.fetch(s.offset, s.length, r);
|
|
2543
|
+
return this.run(i, t, n, r);
|
|
2544
|
+
}
|
|
2545
|
+
/** Run a request using all the middleware */
|
|
2546
|
+
async run(t, n, r, o) {
|
|
2547
|
+
const i = this.middleware;
|
|
2548
|
+
if (i == null)
|
|
2549
|
+
return t({ source: this, offset: n, length: r, signal: o?.signal });
|
|
2550
|
+
function s(a, l) {
|
|
2551
|
+
return (c) => a.fetch(c, l);
|
|
2552
|
+
}
|
|
2553
|
+
for (let a = i.length - 1; a >= 0; a--)
|
|
2554
|
+
t = s(i[a], t);
|
|
2555
|
+
return t({ source: this, offset: n, length: r, signal: o?.signal });
|
|
2556
|
+
}
|
|
2557
|
+
}
|
|
2558
|
+
function tr(e) {
|
|
2559
|
+
try {
|
|
2560
|
+
return new URL(e);
|
|
2561
|
+
} catch {
|
|
2562
|
+
return null;
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
class nr {
|
|
2566
|
+
name = "source:chunk";
|
|
2567
|
+
/** Number of bytes to chunk requests into */
|
|
2568
|
+
chunkSize;
|
|
2569
|
+
constructor(t) {
|
|
2570
|
+
this.chunkSize = t.size ?? 32 * 1024;
|
|
2571
|
+
}
|
|
2572
|
+
async fetch(t, n) {
|
|
2573
|
+
if (t.offset < 0 || t.length == null)
|
|
2574
|
+
return n(t);
|
|
2575
|
+
const r = Math.floor(t.offset / this.chunkSize), o = Math.ceil((t.offset + t.length) / this.chunkSize), i = t.source.metadata?.size;
|
|
2576
|
+
if (i != null && t.offset + t.length > i)
|
|
2577
|
+
throw new B(`Request outside of bounds ${le.toRange(t.offset, t.length)}`, 416, t.source);
|
|
2578
|
+
const s = r * this.chunkSize, l = (i != null ? Math.min(o * this.chunkSize, i) : o * this.chunkSize) - s, c = t.offset - s;
|
|
2579
|
+
return o - r > 1 ? (await this.fetchChunks(t, r, o)).slice(c, c + t.length) : t.offset === s && t.length === l ? n(t) : (await n({ ...t, offset: s, length: l })).slice(c, c + t.length);
|
|
2580
|
+
}
|
|
2581
|
+
async fetchChunks(t, n, r) {
|
|
2582
|
+
const o = [], i = t.source.metadata?.size ?? r * this.chunkSize;
|
|
2583
|
+
for (let l = n; l < r; l++) {
|
|
2584
|
+
const c = l * this.chunkSize, h = Math.min(c + this.chunkSize, i) - c;
|
|
2585
|
+
o.push(t.source.fetch(l * this.chunkSize, h, t.signal ? { signal: t.signal } : void 0));
|
|
2586
|
+
}
|
|
2587
|
+
const s = await Promise.all(o), a = new Uint8Array(o.length * this.chunkSize);
|
|
2588
|
+
for (let l = 0; l < s.length; l++)
|
|
2589
|
+
a.set(new Uint8Array(s[l]), l * this.chunkSize);
|
|
2590
|
+
return a.buffer;
|
|
2591
|
+
}
|
|
2592
|
+
}
|
|
2593
|
+
function qe(e) {
|
|
2594
|
+
const t = {}, n = e.headers.get("content-length");
|
|
2595
|
+
n && (t.size = parseInt(n));
|
|
2596
|
+
const r = e.headers.get("content-range");
|
|
2597
|
+
return r != null && (t.size = le.parseSize(r)), t.eTag = e.headers.get("etag") ?? void 0, t.contentType = e.headers.get("content-type") ?? void 0, t.contentDisposition = e.headers.get("content-disposition") ?? void 0, t.cacheControl = e.headers.get("cache-control") ?? void 0, t.contentEncoding = e.headers.get("content-encoding") ?? void 0, t;
|
|
2598
|
+
}
|
|
2599
|
+
class Y {
|
|
2600
|
+
constructor(t, n) {
|
|
2601
|
+
this.type = "http", this.url = typeof t == "string" ? Y.tryUrl(t) : t, this.headers = n;
|
|
2602
|
+
}
|
|
2603
|
+
/** Attempt to parse a relative string into a URL */
|
|
2604
|
+
static tryUrl(t) {
|
|
2605
|
+
try {
|
|
2606
|
+
return new URL(t);
|
|
2607
|
+
} catch {
|
|
2608
|
+
return typeof document < "u" ? new URL(t, document.baseURI) : new URL(t, import.meta.url);
|
|
2609
|
+
}
|
|
2610
|
+
}
|
|
2611
|
+
head() {
|
|
2612
|
+
return this._head ? this._head : (this._head = Y.fetch(this.url, { method: "HEAD", headers: this.headers }).then((t) => {
|
|
2613
|
+
if (!t.ok)
|
|
2614
|
+
throw delete this._head, new Error(`Failed to HEAD ${this.url.href}`, { cause: { statusCode: t.status, msg: t.statusText } });
|
|
2615
|
+
return this.metadata = qe(t), this.metadata;
|
|
2616
|
+
}), this._head);
|
|
2617
|
+
}
|
|
2618
|
+
async fetch(t, n, r) {
|
|
2619
|
+
try {
|
|
2620
|
+
const o = { range: le.toRange(t, n), ...this.headers }, i = await Y.fetch(this.url, { headers: o, signal: r?.signal });
|
|
2621
|
+
if (!i.ok)
|
|
2622
|
+
throw new B(`Failed to fetch ${this.url.href} ${o.range}`, i.status, this, new Error(i.statusText));
|
|
2623
|
+
const s = qe(i);
|
|
2624
|
+
if (this.metadata == null)
|
|
2625
|
+
this.metadata = s;
|
|
2626
|
+
else if (this.metadata.eTag && this.metadata.eTag !== s.eTag)
|
|
2627
|
+
throw new B(`ETag conflict ${this.url.href} ${o.range} expected: ${this.metadata.eTag} got: ${s.eTag}`, 409, this);
|
|
2628
|
+
return i.arrayBuffer();
|
|
2629
|
+
} catch (o) {
|
|
2630
|
+
throw B.is(o) && o.source === this ? o : new B(`Failed to fetch: ${this.url.href}`, 500, this, o);
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
Y.fetch = (e, t) => fetch(e, t);
|
|
2635
|
+
function rr(e) {
|
|
2636
|
+
if (typeof e != "string")
|
|
2637
|
+
return e;
|
|
2638
|
+
const t = tr(e);
|
|
2639
|
+
return t || new URL("memory://" + e);
|
|
2640
|
+
}
|
|
2641
|
+
class xe {
|
|
2642
|
+
url;
|
|
2643
|
+
type = "memory";
|
|
2644
|
+
data;
|
|
2645
|
+
metadata;
|
|
2646
|
+
static toArrayBuffer(t) {
|
|
2647
|
+
return t instanceof ArrayBuffer ? t : t.byteLength === t.buffer.byteLength ? t.buffer : t.buffer.slice(t.byteOffset, t.byteOffset + t.byteLength);
|
|
2648
|
+
}
|
|
2649
|
+
constructor(t, n) {
|
|
2650
|
+
const r = xe.toArrayBuffer(n ?? new Uint8Array());
|
|
2651
|
+
this.url = rr(t), this.data = r, this.metadata = { size: r.byteLength };
|
|
2652
|
+
}
|
|
2653
|
+
head() {
|
|
2654
|
+
return Promise.resolve({ size: this.data.byteLength });
|
|
2655
|
+
}
|
|
2656
|
+
fetch(t, n) {
|
|
2657
|
+
if (t < 0 && (t = this.data.byteLength + t), t > this.data.byteLength)
|
|
2658
|
+
throw new B(`Read offset outside of file bounds range:${le.toRange(t, n)} fileSize:${this.data.byteLength}`, 416, this);
|
|
2659
|
+
return Promise.resolve(this.data.slice(t, n == null ? void 0 : t + n));
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
const pt = "https://proj.org/schemas/v0.7/projjson.schema.json", or = 1, ir = 2, ee = 32767, Qe = 1, sr = 2, ar = 3, lr = 4, cr = 5, ur = 6, hr = 7, dr = 8, pr = 9, mr = 10, gr = 11, fr = 12, yr = 14, wr = 15, Pr = 16, br = 17, vr = 18, Sr = 21, Lr = 22, Cr = 24, jr = 26, xr = 27, mt = 9102, Or = 9101, Ar = 9105, Er = {
|
|
2663
|
+
[mt]: "degree",
|
|
2664
|
+
[Or]: "radian",
|
|
2665
|
+
[Ar]: "grad"
|
|
2666
|
+
}, gt = 9001, Ir = 9002, Mr = 9003, Rr = {
|
|
2667
|
+
type: "LinearUnit",
|
|
2668
|
+
name: "US survey foot",
|
|
2669
|
+
conversion_factor: 0.30480060960121924
|
|
2670
|
+
}, zr = {
|
|
2671
|
+
[gt]: "metre",
|
|
2672
|
+
[Ir]: "foot",
|
|
2673
|
+
[Mr]: Rr
|
|
2674
|
+
};
|
|
2675
|
+
function Fr(e) {
|
|
2676
|
+
const t = e.modelType;
|
|
2677
|
+
if (t === or)
|
|
2678
|
+
return Nr(e);
|
|
2679
|
+
if (t === ir)
|
|
2680
|
+
return Dr(e);
|
|
2681
|
+
throw new Error(`Unsupported GeoTIFF model type: ${t}`);
|
|
2682
|
+
}
|
|
2683
|
+
function Dr(e) {
|
|
2684
|
+
const t = e.geodeticCRS;
|
|
2685
|
+
return t !== null && t !== ee ? t : ft(e, pt);
|
|
2686
|
+
}
|
|
2687
|
+
function Nr(e) {
|
|
2688
|
+
const t = e.projectedCRS;
|
|
2689
|
+
return t !== null && t !== ee ? t : Ur(e);
|
|
2690
|
+
}
|
|
2691
|
+
function ft(e, t) {
|
|
2692
|
+
const n = Br(e);
|
|
2693
|
+
let r = "Greenwich", o = 0;
|
|
2694
|
+
e.primeMeridian !== null && e.primeMeridian !== ee ? r = `EPSG:${e.primeMeridian}` : e.primeMeridianLongitude !== null && (o = e.primeMeridianLongitude, r = "User-defined");
|
|
2695
|
+
let i;
|
|
2696
|
+
e.geodeticDatum !== null && e.geodeticDatum !== ee ? i = {
|
|
2697
|
+
type: "GeodeticReferenceFrame",
|
|
2698
|
+
name: `Unknown datum based upon EPSG ${e.geodeticDatum} ellipsoid`
|
|
2699
|
+
} : i = {
|
|
2700
|
+
type: "GeodeticReferenceFrame",
|
|
2701
|
+
name: e.geodeticCitation ?? "User-defined",
|
|
2702
|
+
ellipsoid: n,
|
|
2703
|
+
prime_meridian: { name: r, longitude: o }
|
|
2704
|
+
};
|
|
2705
|
+
const s = {
|
|
2706
|
+
type: "GeographicCRS",
|
|
2707
|
+
name: e.geodeticCitation ?? "User-defined",
|
|
2708
|
+
datum: i,
|
|
2709
|
+
coordinate_system: Kr(e)
|
|
2710
|
+
};
|
|
2711
|
+
return t !== void 0 && (s.$schema = t), s;
|
|
2712
|
+
}
|
|
2713
|
+
function Ur(e) {
|
|
2714
|
+
const t = ft(e), n = Gr(e), r = _r(e);
|
|
2715
|
+
return {
|
|
2716
|
+
type: "ProjectedCRS",
|
|
2717
|
+
$schema: pt,
|
|
2718
|
+
name: e.projectedCitation ?? e.citation ?? "User-defined",
|
|
2719
|
+
base_crs: t,
|
|
2720
|
+
conversion: n,
|
|
2721
|
+
coordinate_system: r
|
|
2722
|
+
};
|
|
2723
|
+
}
|
|
2724
|
+
function Br(e) {
|
|
2725
|
+
if (e.ellipsoid !== null && e.ellipsoid !== ee) {
|
|
2726
|
+
const n = {
|
|
2727
|
+
name: `EPSG ellipsoid ${e.ellipsoid}`
|
|
2728
|
+
};
|
|
2729
|
+
return e.ellipsoidSemiMajorAxis !== null && (n.semi_major_axis = e.ellipsoidSemiMajorAxis), e.ellipsoidInvFlattening !== null ? n.inverse_flattening = e.ellipsoidInvFlattening : e.ellipsoidSemiMinorAxis !== null && (n.semi_minor_axis = e.ellipsoidSemiMinorAxis), n;
|
|
2730
|
+
}
|
|
2731
|
+
if (e.ellipsoidSemiMajorAxis === null)
|
|
2732
|
+
throw new Error("User-defined ellipsoid requires ellipsoidSemiMajorAxis");
|
|
2733
|
+
const t = {
|
|
2734
|
+
name: e.geodeticCitation ?? "User-defined",
|
|
2735
|
+
semi_major_axis: e.ellipsoidSemiMajorAxis
|
|
2736
|
+
};
|
|
2737
|
+
if (e.ellipsoidInvFlattening !== null)
|
|
2738
|
+
t.inverse_flattening = e.ellipsoidInvFlattening;
|
|
2739
|
+
else if (e.ellipsoidSemiMinorAxis !== null)
|
|
2740
|
+
t.semi_minor_axis = e.ellipsoidSemiMinorAxis;
|
|
2741
|
+
else
|
|
2742
|
+
throw new Error("User-defined ellipsoid requires ellipsoidInvFlattening or ellipsoidSemiMinorAxis");
|
|
2743
|
+
return t;
|
|
2744
|
+
}
|
|
2745
|
+
function Gr(e) {
|
|
2746
|
+
const t = e.projMethod;
|
|
2747
|
+
if (t === null)
|
|
2748
|
+
throw new Error("User-defined projected CRS requires projMethod");
|
|
2749
|
+
const n = (i, s, a = 0) => ({
|
|
2750
|
+
name: i,
|
|
2751
|
+
value: s ?? a,
|
|
2752
|
+
unit: "degree"
|
|
2753
|
+
}), r = (i, s, a = 0) => ({
|
|
2754
|
+
name: i,
|
|
2755
|
+
value: s ?? a,
|
|
2756
|
+
unit: "metre"
|
|
2757
|
+
}), o = (i, s, a = 1) => ({
|
|
2758
|
+
name: i,
|
|
2759
|
+
value: s ?? a,
|
|
2760
|
+
unit: "unity"
|
|
2761
|
+
});
|
|
2762
|
+
switch (t) {
|
|
2763
|
+
case Qe:
|
|
2764
|
+
case sr:
|
|
2765
|
+
case xr: {
|
|
2766
|
+
const i = t === Qe ? "Transverse Mercator" : "Transverse Mercator (South Orientated)";
|
|
2767
|
+
return {
|
|
2768
|
+
name: i,
|
|
2769
|
+
method: { name: i },
|
|
2770
|
+
parameters: [
|
|
2771
|
+
n("Latitude of natural origin", e.projNatOriginLat),
|
|
2772
|
+
n("Longitude of natural origin", e.projNatOriginLong),
|
|
2773
|
+
o("Scale factor at natural origin", e.projScaleAtNatOrigin),
|
|
2774
|
+
r("False easting", e.projFalseEasting),
|
|
2775
|
+
r("False northing", e.projFalseNorthing)
|
|
2776
|
+
]
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
case ar:
|
|
2780
|
+
case lr:
|
|
2781
|
+
case cr:
|
|
2782
|
+
case ur: {
|
|
2783
|
+
const i = "Hotine Oblique Mercator (variant B)";
|
|
2784
|
+
return {
|
|
2785
|
+
name: i,
|
|
2786
|
+
method: { name: i },
|
|
2787
|
+
parameters: [
|
|
2788
|
+
n("Latitude of projection centre", e.projCenterLat),
|
|
2789
|
+
n("Longitude of projection centre", e.projCenterLong),
|
|
2790
|
+
n("Azimuth of initial line", e.projAzimuthAngle),
|
|
2791
|
+
n("Angle from Rectified to Skew Grid", e.projAzimuthAngle),
|
|
2792
|
+
o("Scale factor on initial line", e.projScaleAtCenter),
|
|
2793
|
+
r("Easting at projection centre", e.projCenterEasting),
|
|
2794
|
+
r("Northing at projection centre", e.projCenterNorthing)
|
|
2795
|
+
]
|
|
2796
|
+
};
|
|
2797
|
+
}
|
|
2798
|
+
case hr: {
|
|
2799
|
+
const i = "Mercator (variant A)";
|
|
2800
|
+
return {
|
|
2801
|
+
name: i,
|
|
2802
|
+
method: { name: i },
|
|
2803
|
+
parameters: [
|
|
2804
|
+
n("Latitude of natural origin", e.projNatOriginLat),
|
|
2805
|
+
n("Longitude of natural origin", e.projNatOriginLong),
|
|
2806
|
+
o("Scale factor at natural origin", e.projScaleAtNatOrigin),
|
|
2807
|
+
r("False easting", e.projFalseEasting),
|
|
2808
|
+
r("False northing", e.projFalseNorthing)
|
|
2809
|
+
]
|
|
2810
|
+
};
|
|
2811
|
+
}
|
|
2812
|
+
case dr: {
|
|
2813
|
+
const i = "Lambert Conic Conformal (2SP)";
|
|
2814
|
+
return {
|
|
2815
|
+
name: i,
|
|
2816
|
+
method: { name: i },
|
|
2817
|
+
parameters: [
|
|
2818
|
+
n("Latitude of false origin", e.projFalseOriginLat ?? e.projNatOriginLat),
|
|
2819
|
+
n("Longitude of false origin", e.projFalseOriginLong ?? e.projNatOriginLong),
|
|
2820
|
+
n("Latitude of 1st standard parallel", e.projStdParallel1),
|
|
2821
|
+
n("Latitude of 2nd standard parallel", e.projStdParallel2),
|
|
2822
|
+
r("Easting at false origin", e.projFalseOriginEasting ?? e.projFalseEasting),
|
|
2823
|
+
r("Northing at false origin", e.projFalseOriginNorthing ?? e.projFalseNorthing)
|
|
2824
|
+
]
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
case pr: {
|
|
2828
|
+
const i = "Lambert Conic Conformal (1SP)";
|
|
2829
|
+
return {
|
|
2830
|
+
name: i,
|
|
2831
|
+
method: { name: i },
|
|
2832
|
+
parameters: [
|
|
2833
|
+
n("Latitude of natural origin", e.projNatOriginLat),
|
|
2834
|
+
n("Longitude of natural origin", e.projNatOriginLong),
|
|
2835
|
+
o("Scale factor at natural origin", e.projScaleAtNatOrigin),
|
|
2836
|
+
r("False easting", e.projFalseEasting),
|
|
2837
|
+
r("False northing", e.projFalseNorthing)
|
|
2838
|
+
]
|
|
2839
|
+
};
|
|
2840
|
+
}
|
|
2841
|
+
case mr: {
|
|
2842
|
+
const i = "Lambert Azimuthal Equal Area";
|
|
2843
|
+
return {
|
|
2844
|
+
name: i,
|
|
2845
|
+
method: { name: i },
|
|
2846
|
+
parameters: [
|
|
2847
|
+
n("Latitude of natural origin", e.projCenterLat),
|
|
2848
|
+
n("Longitude of natural origin", e.projCenterLong),
|
|
2849
|
+
r("False easting", e.projFalseEasting),
|
|
2850
|
+
r("False northing", e.projFalseNorthing)
|
|
2851
|
+
]
|
|
2852
|
+
};
|
|
2853
|
+
}
|
|
2854
|
+
case gr: {
|
|
2855
|
+
const i = "Albers Equal Area";
|
|
2856
|
+
return {
|
|
2857
|
+
name: i,
|
|
2858
|
+
method: { name: i },
|
|
2859
|
+
parameters: [
|
|
2860
|
+
n("Latitude of false origin", e.projFalseOriginLat ?? e.projNatOriginLat),
|
|
2861
|
+
n("Longitude of false origin", e.projFalseOriginLong ?? e.projNatOriginLong),
|
|
2862
|
+
n("Latitude of 1st standard parallel", e.projStdParallel1),
|
|
2863
|
+
n("Latitude of 2nd standard parallel", e.projStdParallel2),
|
|
2864
|
+
r("Easting at false origin", e.projFalseOriginEasting ?? e.projFalseEasting),
|
|
2865
|
+
r("Northing at false origin", e.projFalseOriginNorthing ?? e.projFalseNorthing)
|
|
2866
|
+
]
|
|
2867
|
+
};
|
|
2868
|
+
}
|
|
2869
|
+
case fr: {
|
|
2870
|
+
const i = "Modified Azimuthal Equidistant";
|
|
2871
|
+
return {
|
|
2872
|
+
name: i,
|
|
2873
|
+
method: { name: i },
|
|
2874
|
+
parameters: [
|
|
2875
|
+
n("Latitude of natural origin", e.projCenterLat),
|
|
2876
|
+
n("Longitude of natural origin", e.projCenterLong),
|
|
2877
|
+
r("False easting", e.projFalseEasting),
|
|
2878
|
+
r("False northing", e.projFalseNorthing)
|
|
2879
|
+
]
|
|
2880
|
+
};
|
|
2881
|
+
}
|
|
2882
|
+
case yr: {
|
|
2883
|
+
const i = "Stereographic";
|
|
2884
|
+
return {
|
|
2885
|
+
name: i,
|
|
2886
|
+
method: { name: i },
|
|
2887
|
+
parameters: [
|
|
2888
|
+
n("Latitude of natural origin", e.projCenterLat),
|
|
2889
|
+
n("Longitude of natural origin", e.projCenterLong),
|
|
2890
|
+
o("Scale factor at natural origin", e.projScaleAtCenter),
|
|
2891
|
+
r("False easting", e.projFalseEasting),
|
|
2892
|
+
r("False northing", e.projFalseNorthing)
|
|
2893
|
+
]
|
|
2894
|
+
};
|
|
2895
|
+
}
|
|
2896
|
+
case wr: {
|
|
2897
|
+
const i = "Polar Stereographic (variant B)";
|
|
2898
|
+
return {
|
|
2899
|
+
name: i,
|
|
2900
|
+
method: { name: i },
|
|
2901
|
+
parameters: [
|
|
2902
|
+
n("Latitude of standard parallel", e.projNatOriginLat ?? e.projStdParallel1),
|
|
2903
|
+
n("Longitude of origin", e.projStraightVertPoleLong ?? e.projNatOriginLong),
|
|
2904
|
+
r("False easting", e.projFalseEasting),
|
|
2905
|
+
r("False northing", e.projFalseNorthing)
|
|
2906
|
+
]
|
|
2907
|
+
};
|
|
2908
|
+
}
|
|
2909
|
+
case Pr: {
|
|
2910
|
+
const i = "Oblique Stereographic";
|
|
2911
|
+
return {
|
|
2912
|
+
name: i,
|
|
2913
|
+
method: { name: i },
|
|
2914
|
+
parameters: [
|
|
2915
|
+
n("Latitude of natural origin", e.projCenterLat),
|
|
2916
|
+
n("Longitude of natural origin", e.projCenterLong),
|
|
2917
|
+
o("Scale factor at natural origin", e.projScaleAtCenter),
|
|
2918
|
+
r("False easting", e.projFalseEasting),
|
|
2919
|
+
r("False northing", e.projFalseNorthing)
|
|
2920
|
+
]
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
case br: {
|
|
2924
|
+
const i = "Equidistant Cylindrical";
|
|
2925
|
+
return {
|
|
2926
|
+
name: i,
|
|
2927
|
+
method: { name: i },
|
|
2928
|
+
parameters: [
|
|
2929
|
+
n("Latitude of 1st standard parallel", e.projStdParallel1 ?? e.projCenterLat),
|
|
2930
|
+
n("Longitude of natural origin", e.projCenterLong),
|
|
2931
|
+
r("False easting", e.projFalseEasting),
|
|
2932
|
+
r("False northing", e.projFalseNorthing)
|
|
2933
|
+
]
|
|
2934
|
+
};
|
|
2935
|
+
}
|
|
2936
|
+
case vr: {
|
|
2937
|
+
const i = "Cassini-Soldner";
|
|
2938
|
+
return {
|
|
2939
|
+
name: i,
|
|
2940
|
+
method: { name: i },
|
|
2941
|
+
parameters: [
|
|
2942
|
+
n("Latitude of natural origin", e.projNatOriginLat),
|
|
2943
|
+
n("Longitude of natural origin", e.projNatOriginLong),
|
|
2944
|
+
r("False easting", e.projFalseEasting),
|
|
2945
|
+
r("False northing", e.projFalseNorthing)
|
|
2946
|
+
]
|
|
2947
|
+
};
|
|
2948
|
+
}
|
|
2949
|
+
case Lr: {
|
|
2950
|
+
const i = "American Polyconic";
|
|
2951
|
+
return {
|
|
2952
|
+
name: i,
|
|
2953
|
+
method: { name: i },
|
|
2954
|
+
parameters: [
|
|
2955
|
+
n("Latitude of natural origin", e.projNatOriginLat),
|
|
2956
|
+
n("Longitude of natural origin", e.projNatOriginLong),
|
|
2957
|
+
r("False easting", e.projFalseEasting),
|
|
2958
|
+
r("False northing", e.projFalseNorthing)
|
|
2959
|
+
]
|
|
2960
|
+
};
|
|
2961
|
+
}
|
|
2962
|
+
case Cr: {
|
|
2963
|
+
const i = "Sinusoidal";
|
|
2964
|
+
return {
|
|
2965
|
+
name: i,
|
|
2966
|
+
method: { name: i },
|
|
2967
|
+
parameters: [
|
|
2968
|
+
n("Longitude of natural origin", e.projCenterLong),
|
|
2969
|
+
r("False easting", e.projFalseEasting),
|
|
2970
|
+
r("False northing", e.projFalseNorthing)
|
|
2971
|
+
]
|
|
2972
|
+
};
|
|
2973
|
+
}
|
|
2974
|
+
case Sr: {
|
|
2975
|
+
const i = "Orthographic";
|
|
2976
|
+
return {
|
|
2977
|
+
name: i,
|
|
2978
|
+
method: { name: i },
|
|
2979
|
+
parameters: [
|
|
2980
|
+
n("Latitude of natural origin", e.projCenterLat),
|
|
2981
|
+
n("Longitude of natural origin", e.projCenterLong),
|
|
2982
|
+
r("False easting", e.projFalseEasting),
|
|
2983
|
+
r("False northing", e.projFalseNorthing)
|
|
2984
|
+
]
|
|
2985
|
+
};
|
|
2986
|
+
}
|
|
2987
|
+
case jr: {
|
|
2988
|
+
const i = "New Zealand Map Grid";
|
|
2989
|
+
return {
|
|
2990
|
+
name: i,
|
|
2991
|
+
method: { name: i },
|
|
2992
|
+
parameters: [
|
|
2993
|
+
n("Latitude of natural origin", e.projNatOriginLat),
|
|
2994
|
+
n("Longitude of natural origin", e.projNatOriginLong),
|
|
2995
|
+
r("False easting", e.projFalseEasting),
|
|
2996
|
+
r("False northing", e.projFalseNorthing)
|
|
2997
|
+
]
|
|
2998
|
+
};
|
|
2999
|
+
}
|
|
3000
|
+
default:
|
|
3001
|
+
throw new Error(`Unsupported coordinate transformation type: ${t}`);
|
|
3002
|
+
}
|
|
3003
|
+
}
|
|
3004
|
+
function Kr(e) {
|
|
3005
|
+
const t = Er[e.angularUnits ?? mt] ?? "degree";
|
|
3006
|
+
return {
|
|
3007
|
+
subtype: "ellipsoidal",
|
|
3008
|
+
axis: [
|
|
3009
|
+
{
|
|
3010
|
+
name: "Geodetic latitude",
|
|
3011
|
+
abbreviation: "Lat",
|
|
3012
|
+
direction: "north",
|
|
3013
|
+
unit: t
|
|
3014
|
+
},
|
|
3015
|
+
{
|
|
3016
|
+
name: "Geodetic longitude",
|
|
3017
|
+
abbreviation: "Lon",
|
|
3018
|
+
direction: "east",
|
|
3019
|
+
unit: t
|
|
3020
|
+
}
|
|
3021
|
+
]
|
|
3022
|
+
};
|
|
3023
|
+
}
|
|
3024
|
+
function _r(e) {
|
|
3025
|
+
const t = zr[e.projLinearUnits ?? gt] ?? "metre";
|
|
3026
|
+
return {
|
|
3027
|
+
subtype: "Cartesian",
|
|
3028
|
+
axis: [
|
|
3029
|
+
{ name: "Easting", abbreviation: "E", direction: "east", unit: t },
|
|
3030
|
+
{ name: "Northing", abbreviation: "N", direction: "north", unit: t }
|
|
3031
|
+
]
|
|
3032
|
+
};
|
|
3033
|
+
}
|
|
3034
|
+
const Xr = 1024 * 1024, Wr = 16 * 1024 * 1024, Te = 6;
|
|
3035
|
+
async function Hr(e, t, n) {
|
|
3036
|
+
if (t.length === 0)
|
|
3037
|
+
return [];
|
|
3038
|
+
const r = n?.coalesce ?? Xr, o = n?.maxRangeSize ?? Wr, i = n?.signal, s = kr(t, r, o), a = await Vr(e, s, i), l = new Array(t.length);
|
|
3039
|
+
for (let c = 0; c < t.length; c++) {
|
|
3040
|
+
const u = t[c], h = Zr(s, u.offset), p = s[h], d = a[h], g = u.offset - p.offset, f = g + u.length;
|
|
3041
|
+
if (f > d.byteLength)
|
|
3042
|
+
throw new Error(`Failed to fetch bytes from offset:${u.offset} wanted:${u.length} got:${d.byteLength - g}`);
|
|
3043
|
+
l[c] = d.slice(g, f);
|
|
3044
|
+
}
|
|
3045
|
+
return l;
|
|
3046
|
+
}
|
|
3047
|
+
function kr(e, t, n) {
|
|
3048
|
+
const r = [...e].sort((s, a) => s.offset - a.offset), o = [];
|
|
3049
|
+
let i = null;
|
|
3050
|
+
for (const s of r) {
|
|
3051
|
+
if (i == null) {
|
|
3052
|
+
i = { offset: s.offset, length: s.length };
|
|
3053
|
+
continue;
|
|
3054
|
+
}
|
|
3055
|
+
const a = i.offset + i.length, l = s.offset + s.length, c = s.offset - a, u = Math.max(a, l), h = u - i.offset;
|
|
3056
|
+
c <= t && h <= n ? i.length = u - i.offset : (o.push(i), i = { offset: s.offset, length: s.length });
|
|
3057
|
+
}
|
|
3058
|
+
return i != null && o.push(i), o;
|
|
3059
|
+
}
|
|
3060
|
+
function Zr(e, t) {
|
|
3061
|
+
let n = 0, r = e.length - 1;
|
|
3062
|
+
for (; n < r; ) {
|
|
3063
|
+
const o = n + r + 1 >>> 1;
|
|
3064
|
+
e[o].offset <= t ? n = o : r = o - 1;
|
|
3065
|
+
}
|
|
3066
|
+
return n;
|
|
3067
|
+
}
|
|
3068
|
+
async function Vr(e, t, n) {
|
|
3069
|
+
const r = new Array(t.length);
|
|
3070
|
+
for (let o = 0; o < t.length; o += Te) {
|
|
3071
|
+
const i = t.slice(o, o + Te), s = await Promise.all(i.map((a) => e.fetch(a.offset, a.length, { signal: n })));
|
|
3072
|
+
for (let a = 0; a < s.length; a++)
|
|
3073
|
+
r[o + a] = s[a];
|
|
3074
|
+
}
|
|
3075
|
+
return r;
|
|
3076
|
+
}
|
|
3077
|
+
async function yt(e, t, n, { boundless: r = !0, pool: o, signal: i } = {}) {
|
|
3078
|
+
const s = qr(e, t, n, { signal: i }), a = e.maskImage != null ? vt(e.maskImage, t, n, e.dataSource, {
|
|
3079
|
+
signal: i,
|
|
3080
|
+
debug: e._debug ? { label: "mask" } : void 0
|
|
3081
|
+
}) : Promise.resolve(null), [l, c] = await Promise.all([s, a]);
|
|
3082
|
+
return wt(e, t, n, l, c, { boundless: r, pool: o });
|
|
3083
|
+
}
|
|
3084
|
+
async function wt(e, t, n, r, o, { boundless: i, pool: s }) {
|
|
3085
|
+
const { bitsPerSample: a, predictor: l, planarConfiguration: c, sampleFormat: u, lercParameters: h } = e.cachedTags, { sampleFormat: p, bitsPerSample: d } = jt(u, a), g = ae(e.transform, Le(t * e.tileWidth, n * e.tileHeight)), f = e.image.value(m.SamplesPerPixel) ?? 1, y = {
|
|
3086
|
+
sampleFormat: p,
|
|
3087
|
+
bitsPerSample: d,
|
|
3088
|
+
samplesPerPixel: f,
|
|
3089
|
+
width: e.tileWidth,
|
|
3090
|
+
height: e.tileHeight,
|
|
3091
|
+
predictor: l,
|
|
3092
|
+
planarConfiguration: c,
|
|
3093
|
+
lercParameters: h
|
|
3094
|
+
}, [j, b] = await Promise.all([
|
|
3095
|
+
Jr(r, y, s),
|
|
3096
|
+
o != null && e.maskImage != null ? Yr(o, e.maskImage, s) : Promise.resolve(null)
|
|
3097
|
+
]), S = {
|
|
3098
|
+
...j,
|
|
3099
|
+
count: f,
|
|
3100
|
+
height: e.tileHeight,
|
|
3101
|
+
width: e.tileWidth,
|
|
3102
|
+
mask: b,
|
|
3103
|
+
transform: g,
|
|
3104
|
+
crs: e.crs,
|
|
3105
|
+
nodata: e.nodata
|
|
3106
|
+
};
|
|
3107
|
+
return {
|
|
3108
|
+
x: t,
|
|
3109
|
+
y: n,
|
|
3110
|
+
array: i === !0 ? S : eo(e, t, n, S)
|
|
3111
|
+
};
|
|
3112
|
+
}
|
|
3113
|
+
async function Pt(e, t, { boundless: n = !0, pool: r, signal: o } = {}) {
|
|
3114
|
+
if (t.length === 0)
|
|
3115
|
+
return [];
|
|
3116
|
+
const i = Tr(e, t, { signal: o }), s = e.maskImage != null ? Ct(e.maskImage, t, e.dataSource, {
|
|
3117
|
+
signal: o,
|
|
3118
|
+
debug: e._debug ? { label: "mask" } : void 0
|
|
3119
|
+
}) : Promise.resolve(t.map(() => null)), [a, l] = await Promise.all([
|
|
3120
|
+
i,
|
|
3121
|
+
s
|
|
3122
|
+
]);
|
|
3123
|
+
return Promise.all(t.map(([c, u], h) => wt(e, c, u, a[h], l[h] ?? null, {
|
|
3124
|
+
boundless: n,
|
|
3125
|
+
pool: r
|
|
3126
|
+
})));
|
|
3127
|
+
}
|
|
3128
|
+
async function Yr(e, t, n) {
|
|
3129
|
+
const r = t.value(m.SampleFormat) ?? [1], o = t.value(m.BitsPerSample) ?? [8], { sampleFormat: i, bitsPerSample: s } = jt(r, new Uint16Array(o)), { width: a, height: l } = t.tileSize, c = {
|
|
3130
|
+
sampleFormat: i,
|
|
3131
|
+
bitsPerSample: s,
|
|
3132
|
+
samplesPerPixel: t.value(m.SamplesPerPixel) ?? 1,
|
|
3133
|
+
width: a,
|
|
3134
|
+
height: l,
|
|
3135
|
+
predictor: t.value(m.Predictor) ?? 1,
|
|
3136
|
+
planarConfiguration: t.value(m.PlanarConfiguration) ?? U.Contig
|
|
3137
|
+
}, u = (f, y, j) => n ? n.decode(f, y, j) : je(f, y, j), { bytes: h, compression: p } = e, d = await u(h, p, c), g = d.layout === "pixel-interleaved" ? d.data : d.bands[0];
|
|
3138
|
+
if (g instanceof Uint8Array)
|
|
3139
|
+
return g;
|
|
3140
|
+
throw new Error("Expected mask data to decode to Uint8Array");
|
|
3141
|
+
}
|
|
3142
|
+
async function Jr(e, t, n) {
|
|
3143
|
+
const r = (o, i, s) => n ? n.decode(o, i, s) : je(o, i, s);
|
|
3144
|
+
if (Array.isArray(e)) {
|
|
3145
|
+
const o = { ...t, samplesPerPixel: 1 };
|
|
3146
|
+
return { layout: "band-separate", bands: (await Promise.all(e.map(({ bytes: a, compression: l }) => r(a, l, o)))).map((a) => a.layout === "band-separate" ? a.bands[0] : a.data) };
|
|
3147
|
+
} else {
|
|
3148
|
+
const { bytes: o, compression: i } = e;
|
|
3149
|
+
return r(o, i, t);
|
|
3150
|
+
}
|
|
3151
|
+
}
|
|
3152
|
+
async function qr(e, t, n, { signal: r } = {}) {
|
|
3153
|
+
const o = e._debug ? { label: "data" } : void 0;
|
|
3154
|
+
switch (e.cachedTags.planarConfiguration) {
|
|
3155
|
+
case U.Contig: {
|
|
3156
|
+
const i = await vt(e.image, t, n, e.dataSource, {
|
|
3157
|
+
signal: r,
|
|
3158
|
+
debug: o
|
|
3159
|
+
});
|
|
3160
|
+
if (i === null)
|
|
3161
|
+
throw new Error(`Tile at (${t}, ${n}) not found`);
|
|
3162
|
+
return i;
|
|
3163
|
+
}
|
|
3164
|
+
case U.Separate:
|
|
3165
|
+
return await Qr(e, t, n, { signal: r });
|
|
3166
|
+
default:
|
|
3167
|
+
throw new Error(`Unsupported PlanarConfiguration: ${e.cachedTags.planarConfiguration}`);
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
async function bt(e, t, n) {
|
|
3171
|
+
const { x: r, y: o } = e.image.tileCount, i = r * o, s = e.cachedTags.samplesPerPixel, a = [...Array(s).keys()].map((l) => {
|
|
3172
|
+
const c = l * i + n * r + t;
|
|
3173
|
+
return e.image.getTileSize(c);
|
|
3174
|
+
});
|
|
3175
|
+
return Promise.all(a);
|
|
3176
|
+
}
|
|
3177
|
+
async function Qr(e, t, n, { signal: r } = {}) {
|
|
3178
|
+
const o = e._debug ? { label: "data" } : void 0, s = (await bt(e, t, n)).map(async ({ offset: a, imageSize: l }) => {
|
|
3179
|
+
const c = await St(e.image, a, l, e.dataSource, { signal: r, debug: o });
|
|
3180
|
+
if (c === null)
|
|
3181
|
+
throw new Error(`Tile at (${t}, ${n}) not found`);
|
|
3182
|
+
return c;
|
|
3183
|
+
});
|
|
3184
|
+
return Promise.all(s);
|
|
3185
|
+
}
|
|
3186
|
+
async function Tr(e, t, { signal: n } = {}) {
|
|
3187
|
+
const r = e._debug ? { label: "data" } : void 0;
|
|
3188
|
+
switch (e.cachedTags.planarConfiguration) {
|
|
3189
|
+
case U.Contig:
|
|
3190
|
+
return (await Ct(e.image, t, e.dataSource, {
|
|
3191
|
+
signal: n,
|
|
3192
|
+
debug: r
|
|
3193
|
+
})).map((i, s) => {
|
|
3194
|
+
if (i === null) {
|
|
3195
|
+
const [a, l] = t[s];
|
|
3196
|
+
throw new Error(`Tile at (${a}, ${l}) not found`);
|
|
3197
|
+
}
|
|
3198
|
+
return i;
|
|
3199
|
+
});
|
|
3200
|
+
case U.Separate:
|
|
3201
|
+
return $r(e, t, { signal: n });
|
|
3202
|
+
default:
|
|
3203
|
+
throw new Error(`Unsupported PlanarConfiguration: ${e.cachedTags.planarConfiguration}`);
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
async function $r(e, t, { signal: n } = {}) {
|
|
3207
|
+
const r = e._debug ? { label: "data" } : void 0, o = e.cachedTags.samplesPerPixel, s = (await Promise.all(t.map(([l, c]) => bt(e, l, c)))).flatMap((l) => l.map(({ offset: c, imageSize: u }) => ({
|
|
3208
|
+
offset: c,
|
|
3209
|
+
byteCount: u
|
|
3210
|
+
}))), a = await Lt(e.image, s, e.dataSource, { signal: n, debug: r });
|
|
3211
|
+
return t.map(([l, c], u) => a.slice(u * o, u * o + o).map((h) => {
|
|
3212
|
+
if (h === null)
|
|
3213
|
+
throw new Error(`Tile at (${l}, ${c}) not found`);
|
|
3214
|
+
return h;
|
|
3215
|
+
}));
|
|
3216
|
+
}
|
|
3217
|
+
async function vt(e, t, n, r, o) {
|
|
3218
|
+
const { size: i, tileSize: s } = e;
|
|
3219
|
+
if (s == null)
|
|
3220
|
+
throw new Error("Tiff is not tiled");
|
|
3221
|
+
const a = Math.ceil(i.height / s.height), l = Math.ceil(i.width / s.width);
|
|
3222
|
+
if (t >= l || n >= a)
|
|
3223
|
+
throw new Error(`Tile index is outside of range x:${t} >= ${l} or y:${n} >= ${a}`);
|
|
3224
|
+
const c = n * l + t, u = l * a;
|
|
3225
|
+
if (c >= u)
|
|
3226
|
+
throw new Error(`Tile index is outside of tile range: ${c} >= ${u}`);
|
|
3227
|
+
const { offset: h, imageSize: p } = await e.getTileSize(c);
|
|
3228
|
+
return St(e, h, p, r, o);
|
|
3229
|
+
}
|
|
3230
|
+
async function St(e, t, n, r, o) {
|
|
3231
|
+
if (n === 0)
|
|
3232
|
+
return null;
|
|
3233
|
+
o?.debug !== void 0 && console.log(`[geotiff dataSource] ${o.debug.label}: offset=${t} length=${n}`);
|
|
3234
|
+
const i = await r.fetch(t, n, o);
|
|
3235
|
+
if (i.byteLength < n)
|
|
3236
|
+
throw new Error(`Failed to fetch bytes from offset:${t} wanted:${n} got:${i.byteLength}`);
|
|
3237
|
+
const s = e.value(m.Compression) ?? P.None;
|
|
3238
|
+
return s === P.Jpeg ? {
|
|
3239
|
+
bytes: e.getJpegHeader(i),
|
|
3240
|
+
compression: s
|
|
3241
|
+
} : { bytes: i, compression: s };
|
|
3242
|
+
}
|
|
3243
|
+
async function Lt(e, t, n, r) {
|
|
3244
|
+
if (t.length === 0)
|
|
3245
|
+
return [];
|
|
3246
|
+
const o = new Array(t.length), i = [], s = [];
|
|
3247
|
+
for (let c = 0; c < t.length; c++) {
|
|
3248
|
+
const u = t[c];
|
|
3249
|
+
u.offset === 0 || u.byteCount === 0 ? o[c] = null : (s.push(c), i.push({ offset: u.offset, length: u.byteCount }));
|
|
3250
|
+
}
|
|
3251
|
+
if (i.length === 0)
|
|
3252
|
+
return o;
|
|
3253
|
+
if (r?.debug !== void 0)
|
|
3254
|
+
for (const c of i)
|
|
3255
|
+
console.log(`[geotiff dataSource] ${r.debug.label}: offset=${c.offset} length=${c.length}`);
|
|
3256
|
+
const a = await Hr(n, i, {
|
|
3257
|
+
coalesce: r?.coalesce,
|
|
3258
|
+
maxRangeSize: r?.maxRangeSize,
|
|
3259
|
+
signal: r?.signal
|
|
3260
|
+
}), l = e.value(m.Compression) ?? P.None;
|
|
3261
|
+
for (let c = 0; c < a.length; c++) {
|
|
3262
|
+
const u = s[c], h = a[c], p = l === P.Jpeg ? e.getJpegHeader(h) : h;
|
|
3263
|
+
o[u] = { bytes: p, compression: l };
|
|
3264
|
+
}
|
|
3265
|
+
return o;
|
|
3266
|
+
}
|
|
3267
|
+
async function Ct(e, t, n, r) {
|
|
3268
|
+
if (t.length === 0)
|
|
3269
|
+
return [];
|
|
3270
|
+
const { size: o, tileSize: i } = e;
|
|
3271
|
+
if (i == null)
|
|
3272
|
+
throw new Error("Tiff is not tiled");
|
|
3273
|
+
const s = Math.ceil(o.height / i.height), a = Math.ceil(o.width / i.width), l = a * s, c = t.map(([h, p]) => {
|
|
3274
|
+
if (h >= a || p >= s)
|
|
3275
|
+
throw new Error(`Tile index is outside of range x:${h} >= ${a} or y:${p} >= ${s}`);
|
|
3276
|
+
const d = p * a + h;
|
|
3277
|
+
if (d >= l)
|
|
3278
|
+
throw new Error(`Tile index is outside of tile range: ${d} >= ${l}`);
|
|
3279
|
+
return d;
|
|
3280
|
+
}), u = await Promise.all(c.map((h) => e.getTileSize(h)));
|
|
3281
|
+
return Lt(e, u.map((h) => ({ offset: h.offset, byteCount: h.imageSize })), n, r);
|
|
3282
|
+
}
|
|
3283
|
+
function eo(e, t, n, r) {
|
|
3284
|
+
const { width: o, height: i } = e.image.getTileBounds(t, n);
|
|
3285
|
+
if (o === e.tileWidth && i === e.tileHeight)
|
|
3286
|
+
return r;
|
|
3287
|
+
const s = r.mask ? ue(r.mask, e.tileWidth, o, i, 1) : r.mask;
|
|
3288
|
+
if (r.layout === "pixel-interleaved") {
|
|
3289
|
+
const { count: c, data: u } = r, h = ue(u, e.tileWidth, o, i, c);
|
|
3290
|
+
return {
|
|
3291
|
+
...r,
|
|
3292
|
+
width: o,
|
|
3293
|
+
height: i,
|
|
3294
|
+
data: h,
|
|
3295
|
+
mask: s
|
|
3296
|
+
};
|
|
3297
|
+
}
|
|
3298
|
+
const { bands: a } = r, l = a.map((c) => ue(c, e.tileWidth, o, i, 1));
|
|
3299
|
+
return {
|
|
3300
|
+
...r,
|
|
3301
|
+
width: o,
|
|
3302
|
+
height: i,
|
|
3303
|
+
bands: l,
|
|
3304
|
+
mask: s
|
|
3305
|
+
};
|
|
3306
|
+
}
|
|
3307
|
+
function ue(e, t, n, r, o) {
|
|
3308
|
+
const i = t * o, s = n * o, a = new e.constructor(s * r);
|
|
3309
|
+
for (let l = 0; l < r; l++)
|
|
3310
|
+
a.set(e.subarray(l * i, l * i + s), l * s);
|
|
3311
|
+
return a;
|
|
3312
|
+
}
|
|
3313
|
+
function jt(e, t) {
|
|
3314
|
+
const n = new Set(e), r = new Set(t);
|
|
3315
|
+
if (n.size > 1)
|
|
3316
|
+
throw new Error("Multiple sample formats are not supported.");
|
|
3317
|
+
if (r.size > 1)
|
|
3318
|
+
throw new Error("Multiple bits per sample values are not supported.");
|
|
3319
|
+
const o = e[0], i = t[0];
|
|
3320
|
+
if (o === void 0 || i === void 0)
|
|
3321
|
+
throw new Error("SampleFormat and BitsPerSample arrays cannot be empty.");
|
|
3322
|
+
return {
|
|
3323
|
+
sampleFormat: o,
|
|
3324
|
+
bitsPerSample: i
|
|
3325
|
+
};
|
|
3326
|
+
}
|
|
3327
|
+
function to(e, { count: t }) {
|
|
3328
|
+
if (e == null)
|
|
3329
|
+
return null;
|
|
3330
|
+
const o = new DOMParser().parseFromString(e, "text/xml").documentElement;
|
|
3331
|
+
if (o.tagName !== "GDALMetadata")
|
|
3332
|
+
throw new Error("Not a GDALMetadata XML block");
|
|
3333
|
+
const i = /* @__PURE__ */ new Map(), s = Array(t).fill(0), a = Array(t).fill(1), l = (c) => {
|
|
3334
|
+
const u = parseInt(c, 10) + 1;
|
|
3335
|
+
return i.has(u) || i.set(u, {
|
|
3336
|
+
max: null,
|
|
3337
|
+
min: null,
|
|
3338
|
+
mean: null,
|
|
3339
|
+
std: null,
|
|
3340
|
+
validPercent: null
|
|
3341
|
+
}), i.get(u);
|
|
3342
|
+
};
|
|
3343
|
+
for (const c of Array.from(o.querySelectorAll("Item"))) {
|
|
3344
|
+
const u = c.getAttribute("name"), h = c.getAttribute("sample"), p = c.textContent ?? "";
|
|
3345
|
+
if (h !== null)
|
|
3346
|
+
switch (u) {
|
|
3347
|
+
case "STATISTICS_MAXIMUM":
|
|
3348
|
+
l(h).max = parseFloat(p);
|
|
3349
|
+
break;
|
|
3350
|
+
case "STATISTICS_MEAN":
|
|
3351
|
+
l(h).mean = parseFloat(p);
|
|
3352
|
+
break;
|
|
3353
|
+
case "STATISTICS_MINIMUM":
|
|
3354
|
+
l(h).min = parseFloat(p);
|
|
3355
|
+
break;
|
|
3356
|
+
case "STATISTICS_STDDEV":
|
|
3357
|
+
l(h).std = parseFloat(p);
|
|
3358
|
+
break;
|
|
3359
|
+
case "STATISTICS_VALID_PERCENT":
|
|
3360
|
+
l(h).validPercent = parseFloat(p);
|
|
3361
|
+
break;
|
|
3362
|
+
case "OFFSET":
|
|
3363
|
+
s[parseInt(h, 10)] = parseFloat(p);
|
|
3364
|
+
break;
|
|
3365
|
+
case "SCALE":
|
|
3366
|
+
a[parseInt(h, 10)] = parseFloat(p);
|
|
3367
|
+
break;
|
|
3368
|
+
}
|
|
3369
|
+
}
|
|
3370
|
+
return { bandStatistics: i, offsets: s, scales: a };
|
|
3371
|
+
}
|
|
3372
|
+
async function no(e, t = {}) {
|
|
3373
|
+
const { signal: n } = t, r = e.value(m.Compression);
|
|
3374
|
+
if (r === null)
|
|
3375
|
+
throw new Error("Compression tag should always exist.");
|
|
3376
|
+
const [o, i, s, a, l, c, u, h, p, d, g, f, y] = await Promise.all([
|
|
3377
|
+
e.fetch(m.BitsPerSample, { signal: n }),
|
|
3378
|
+
e.fetch(m.ColorMap, { signal: n }),
|
|
3379
|
+
e.fetch(m.GdalNoData, { signal: n }),
|
|
3380
|
+
e.fetch(m.GdalMetadata, { signal: n }),
|
|
3381
|
+
e.fetch(m.LercParameters, { signal: n }),
|
|
3382
|
+
e.fetch(m.ModelPixelScale, { signal: n }),
|
|
3383
|
+
e.fetch(m.ModelTiePoint, { signal: n }),
|
|
3384
|
+
e.fetch(m.ModelTransformation, { signal: n }),
|
|
3385
|
+
e.fetch(m.Photometric, { signal: n }),
|
|
3386
|
+
e.fetch(m.PlanarConfiguration, { signal: n }),
|
|
3387
|
+
e.fetch(m.Predictor, { signal: n }),
|
|
3388
|
+
e.fetch(m.SampleFormat, { signal: n }),
|
|
3389
|
+
e.fetch(m.SamplesPerPixel, { signal: n })
|
|
3390
|
+
]), j = (b) => {
|
|
3391
|
+
throw new Error(`${b} tag should always exist.`);
|
|
3392
|
+
};
|
|
3393
|
+
return o === null && j("BitsPerSample"), y === null && j("SamplesPerPixel"), p === null && j("Photometric"), {
|
|
3394
|
+
bitsPerSample: new Uint16Array(o),
|
|
3395
|
+
colorMap: i ? new Uint16Array(i) : void 0,
|
|
3396
|
+
compression: r,
|
|
3397
|
+
gdalMetadata: a,
|
|
3398
|
+
lercParameters: l,
|
|
3399
|
+
modelTiepoint: u,
|
|
3400
|
+
modelPixelScale: c,
|
|
3401
|
+
modelTransformation: h,
|
|
3402
|
+
nodata: s !== null ? Number(s) : null,
|
|
3403
|
+
photometric: p,
|
|
3404
|
+
// PlanarConfiguration defaults to interleaved/chunky/contig
|
|
3405
|
+
// https://web.archive.org/web/20240329145253/https://www.awaresystems.be/imaging/tiff/tifftags/planarconfiguration.html
|
|
3406
|
+
planarConfiguration: d ?? U.Contig,
|
|
3407
|
+
predictor: g ?? V.None,
|
|
3408
|
+
// Uint is the default sample format according to the spec
|
|
3409
|
+
// https://web.archive.org/web/20240329145340/https://www.awaresystems.be/imaging/tiff/tifftags/sampleformat.html
|
|
3410
|
+
sampleFormat: f ?? [F.Uint],
|
|
3411
|
+
samplesPerPixel: y
|
|
3412
|
+
};
|
|
3413
|
+
}
|
|
3414
|
+
function ro(e) {
|
|
3415
|
+
const t = (n) => e.valueGeo(n) ?? null;
|
|
3416
|
+
return {
|
|
3417
|
+
// Configuration keys
|
|
3418
|
+
modelType: t(w.GTModelTypeGeoKey),
|
|
3419
|
+
rasterType: t(w.GTRasterTypeGeoKey),
|
|
3420
|
+
citation: t(w.GTCitationGeoKey),
|
|
3421
|
+
// Geographic CRS keys
|
|
3422
|
+
geodeticCRS: t(w.GeodeticCRSGeoKey),
|
|
3423
|
+
geodeticCitation: t(w.GeodeticCitationGeoKey),
|
|
3424
|
+
geodeticDatum: t(w.GeodeticDatumGeoKey),
|
|
3425
|
+
primeMeridian: t(w.PrimeMeridianGeoKey),
|
|
3426
|
+
linearUnits: t(w.GeogLinearUnitsGeoKey),
|
|
3427
|
+
linearUnitSize: t(w.GeogLinearUnitSizeGeoKey),
|
|
3428
|
+
angularUnits: t(w.GeogAngularUnitsGeoKey),
|
|
3429
|
+
angularUnitSize: t(w.GeogAngularUnitSizeGeoKey),
|
|
3430
|
+
ellipsoid: t(w.EllipsoidGeoKey),
|
|
3431
|
+
ellipsoidSemiMajorAxis: t(w.EllipsoidSemiMajorAxisGeoKey),
|
|
3432
|
+
ellipsoidSemiMinorAxis: t(w.EllipsoidSemiMinorAxisGeoKey),
|
|
3433
|
+
ellipsoidInvFlattening: t(w.EllipsoidInvFlatteningGeoKey),
|
|
3434
|
+
azimuthUnits: t(w.GeogAzimuthUnitsGeoKey),
|
|
3435
|
+
primeMeridianLongitude: t(w.PrimeMeridianLongitudeGeoKey),
|
|
3436
|
+
toWGS84: t(w.GeogTOWGS84GeoKey),
|
|
3437
|
+
// Projected CRS keys
|
|
3438
|
+
projectedCRS: t(w.ProjectedCRSGeoKey),
|
|
3439
|
+
projectedCitation: t(w.ProjectedCitationGeoKey),
|
|
3440
|
+
projection: t(w.ProjectionGeoKey),
|
|
3441
|
+
projMethod: t(w.ProjMethodGeoKey),
|
|
3442
|
+
projLinearUnits: t(w.ProjLinearUnitsGeoKey),
|
|
3443
|
+
projLinearUnitSize: t(w.ProjLinearUnitSizeGeoKey),
|
|
3444
|
+
projStdParallel1: t(w.ProjStdParallel1GeoKey),
|
|
3445
|
+
projStdParallel2: t(w.ProjStdParallel2GeoKey),
|
|
3446
|
+
projNatOriginLong: t(w.ProjNatOriginLongGeoKey),
|
|
3447
|
+
projNatOriginLat: t(w.ProjNatOriginLatGeoKey),
|
|
3448
|
+
projFalseEasting: t(w.ProjFalseEastingGeoKey),
|
|
3449
|
+
projFalseNorthing: t(w.ProjFalseNorthingGeoKey),
|
|
3450
|
+
projFalseOriginLong: t(w.ProjFalseOriginLongGeoKey),
|
|
3451
|
+
projFalseOriginLat: t(w.ProjFalseOriginLatGeoKey),
|
|
3452
|
+
projFalseOriginEasting: t(w.ProjFalseOriginEastingGeoKey),
|
|
3453
|
+
projFalseOriginNorthing: t(w.ProjFalseOriginNorthingGeoKey),
|
|
3454
|
+
projCenterLong: t(w.ProjCenterLongGeoKey),
|
|
3455
|
+
projCenterLat: t(w.ProjCenterLatGeoKey),
|
|
3456
|
+
projCenterEasting: t(w.ProjCenterEastingGeoKey),
|
|
3457
|
+
projCenterNorthing: t(w.ProjCenterNorthingGeoKey),
|
|
3458
|
+
projScaleAtNatOrigin: t(w.ProjScaleAtNatOriginGeoKey),
|
|
3459
|
+
projScaleAtCenter: t(w.ProjScaleAtCenterGeoKey),
|
|
3460
|
+
projAzimuthAngle: t(w.ProjAzimuthAngleGeoKey),
|
|
3461
|
+
projStraightVertPoleLong: t(w.ProjStraightVertPoleLongGeoKey),
|
|
3462
|
+
projRectifiedGridAngle: t(w.ProjRectifiedGridAngleGeoKey),
|
|
3463
|
+
// Vertical CRS keys
|
|
3464
|
+
verticalCRS: t(w.VerticalGeoKey),
|
|
3465
|
+
verticalCitation: t(w.VerticalCitationGeoKey),
|
|
3466
|
+
verticalDatum: t(w.VerticalDatumGeoKey),
|
|
3467
|
+
verticalUnits: t(w.VerticalUnitsGeoKey)
|
|
3468
|
+
};
|
|
3469
|
+
}
|
|
3470
|
+
function oo({ modelTiepoint: e, modelPixelScale: t, modelTransformation: n, rasterType: r }) {
|
|
3471
|
+
let o;
|
|
3472
|
+
if (e && t)
|
|
3473
|
+
o = io(e, t);
|
|
3474
|
+
else if (n)
|
|
3475
|
+
o = so(n);
|
|
3476
|
+
else
|
|
3477
|
+
throw new Error("The image does not have an affine transformation.");
|
|
3478
|
+
return r === we.PixelIsPoint && (o = ae(o, Le(-0.5, -0.5))), o;
|
|
3479
|
+
}
|
|
3480
|
+
function io(e, t) {
|
|
3481
|
+
const n = e[3], r = e[4], o = t[0], i = -t[1];
|
|
3482
|
+
return [o, 0, n, 0, i, r];
|
|
3483
|
+
}
|
|
3484
|
+
function so(e) {
|
|
3485
|
+
const t = e[3], n = e[7], r = e[1], o = e[4], i = e[0], s = e[5];
|
|
3486
|
+
return [i, r, t, o, s, n];
|
|
3487
|
+
}
|
|
3488
|
+
function xt(e, t, n, r = Math.floor) {
|
|
3489
|
+
const o = de(e.transform), [i, s] = A(o, t, n);
|
|
3490
|
+
return [r(s), r(i)];
|
|
3491
|
+
}
|
|
3492
|
+
function Ot(e, t, n, r = "center") {
|
|
3493
|
+
let o, i;
|
|
3494
|
+
switch (r) {
|
|
3495
|
+
case "center":
|
|
3496
|
+
o = n + 0.5, i = t + 0.5;
|
|
3497
|
+
break;
|
|
3498
|
+
case "ul":
|
|
3499
|
+
o = n, i = t;
|
|
3500
|
+
break;
|
|
3501
|
+
case "ur":
|
|
3502
|
+
o = n + 1, i = t;
|
|
3503
|
+
break;
|
|
3504
|
+
case "ll":
|
|
3505
|
+
o = n, i = t + 1;
|
|
3506
|
+
break;
|
|
3507
|
+
case "lr":
|
|
3508
|
+
o = n + 1, i = t + 1;
|
|
3509
|
+
break;
|
|
3510
|
+
}
|
|
3511
|
+
return A(e.transform, o, i);
|
|
3512
|
+
}
|
|
3513
|
+
class ao {
|
|
3514
|
+
cachedTags;
|
|
3515
|
+
/** The data source used for fetching tile data. */
|
|
3516
|
+
dataSource;
|
|
3517
|
+
/** A reference to the parent GeoTIFF object. */
|
|
3518
|
+
geotiff;
|
|
3519
|
+
/** The GeoKeyDirectory of the primary IFD. */
|
|
3520
|
+
gkd;
|
|
3521
|
+
/** The data IFD for this resolution level. */
|
|
3522
|
+
image;
|
|
3523
|
+
/** The IFD for the mask associated with this overview level, if any. */
|
|
3524
|
+
maskImage = null;
|
|
3525
|
+
constructor(t, n, r, o, i, s) {
|
|
3526
|
+
this.geotiff = t, this.gkd = n, this.image = r, this.maskImage = o, this.cachedTags = i, this.dataSource = s;
|
|
3527
|
+
}
|
|
3528
|
+
/**
|
|
3529
|
+
* The CRS parsed from the GeoKeyDirectory.
|
|
3530
|
+
*
|
|
3531
|
+
* Returns an EPSG code (number) for EPSG-coded CRSes, or a PROJJSON object
|
|
3532
|
+
* for user-defined CRSes. The result is cached after the first access.
|
|
3533
|
+
*
|
|
3534
|
+
* See also {@link GeoTIFF.epsg} for the EPSG code directly from the TIFF tags.
|
|
3535
|
+
*/
|
|
3536
|
+
get crs() {
|
|
3537
|
+
return this.geotiff.crs;
|
|
3538
|
+
}
|
|
3539
|
+
/** Image height in pixels. */
|
|
3540
|
+
get height() {
|
|
3541
|
+
return this.image.size.height;
|
|
3542
|
+
}
|
|
3543
|
+
/** The no data value, or null if not set. */
|
|
3544
|
+
get nodata() {
|
|
3545
|
+
return this.geotiff.nodata;
|
|
3546
|
+
}
|
|
3547
|
+
/** Inherits the {@link GeoTIFF._debug} flag from the parent. */
|
|
3548
|
+
get _debug() {
|
|
3549
|
+
return this.geotiff._debug;
|
|
3550
|
+
}
|
|
3551
|
+
/** The number of tiles in the x and y directions */
|
|
3552
|
+
get tileCount() {
|
|
3553
|
+
return this.image.tileCount;
|
|
3554
|
+
}
|
|
3555
|
+
/** Tile height in pixels. */
|
|
3556
|
+
get tileHeight() {
|
|
3557
|
+
return this.image.tileSize.height;
|
|
3558
|
+
}
|
|
3559
|
+
/** Tile width in pixels. */
|
|
3560
|
+
get tileWidth() {
|
|
3561
|
+
return this.image.tileSize.width;
|
|
3562
|
+
}
|
|
3563
|
+
/**
|
|
3564
|
+
* Return the dataset's georeferencing transformation matrix.
|
|
3565
|
+
*/
|
|
3566
|
+
get transform() {
|
|
3567
|
+
const t = this.geotiff.transform, n = this.geotiff.width / this.width, r = this.geotiff.height / this.height;
|
|
3568
|
+
return ae(t, tn(n, r));
|
|
3569
|
+
}
|
|
3570
|
+
/** Image width in pixels. */
|
|
3571
|
+
get width() {
|
|
3572
|
+
return this.image.size.width;
|
|
3573
|
+
}
|
|
3574
|
+
/** Fetch a single tile from the full-resolution image.
|
|
3575
|
+
*
|
|
3576
|
+
* @param x The tile column index (0-based).
|
|
3577
|
+
* @param y The tile row index (0-based).
|
|
3578
|
+
* @param options Optional parameters for fetching the tile.
|
|
3579
|
+
* @param options.boundless Whether to clip tiles that are partially outside the image bounds. When `true`, no clipping is applied and edge tiles are returned at the full nominal tile size. Defaults to `true`.
|
|
3580
|
+
* @param options.pool An optional {@link DecoderPool} for decoding the tile data. If not provided, a new decoder will be created for each tile.
|
|
3581
|
+
* @param options.signal An optional {@link AbortSignal} to cancel the fetch request.
|
|
3582
|
+
*/
|
|
3583
|
+
async fetchTile(t, n, r = {}) {
|
|
3584
|
+
return await yt(this, t, n, r);
|
|
3585
|
+
}
|
|
3586
|
+
/**
|
|
3587
|
+
* Fetch multiple tiles in parallel.
|
|
3588
|
+
*
|
|
3589
|
+
* A future implementation may coalesce contiguous byte ranges to reduce
|
|
3590
|
+
* the number of HTTP requests.
|
|
3591
|
+
*
|
|
3592
|
+
* @param xy - Array of `[x, y]` tile coordinates.
|
|
3593
|
+
* @param options - Optional parameters (same as {@link fetchTile}).
|
|
3594
|
+
* @returns Array of {@link Tile} objects in the same order as `xy`.
|
|
3595
|
+
*
|
|
3596
|
+
* @see {@link fetchTile} for single-tile fetching.
|
|
3597
|
+
*/
|
|
3598
|
+
async fetchTiles(t, n = {}) {
|
|
3599
|
+
return await Pt(this, t, n);
|
|
3600
|
+
}
|
|
3601
|
+
// TiledMixin
|
|
3602
|
+
// Transform mixin
|
|
3603
|
+
/**
|
|
3604
|
+
* Get the (row, col) pixel index containing the geographic coordinate (x, y).
|
|
3605
|
+
*
|
|
3606
|
+
* @param x x coordinate in the CRS.
|
|
3607
|
+
* @param y y coordinate in the CRS.
|
|
3608
|
+
* @param op Rounding function applied to fractional pixel indices.
|
|
3609
|
+
* Defaults to Math.floor.
|
|
3610
|
+
* @returns [row, col] pixel indices.
|
|
3611
|
+
*/
|
|
3612
|
+
index(t, n, r = Math.floor) {
|
|
3613
|
+
return xt(this, t, n, r);
|
|
3614
|
+
}
|
|
3615
|
+
/**
|
|
3616
|
+
* Get the geographic (x, y) coordinate of the pixel at (row, col).
|
|
3617
|
+
*
|
|
3618
|
+
* @param row Pixel row.
|
|
3619
|
+
* @param col Pixel column.
|
|
3620
|
+
* @param offset Which part of the pixel to return. Defaults to "center".
|
|
3621
|
+
* @returns [x, y] in the CRS.
|
|
3622
|
+
*/
|
|
3623
|
+
xy(t, n, r = "center") {
|
|
3624
|
+
return Ot(this, t, n, r);
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
class _ {
|
|
3628
|
+
/**
|
|
3629
|
+
* Reduced-resolution overview levels, sorted finest-to-coarsest.
|
|
3630
|
+
*
|
|
3631
|
+
* Does not include the full-resolution image — use {@link fetchTile} on the
|
|
3632
|
+
* GeoTIFF instance itself for that.
|
|
3633
|
+
*/
|
|
3634
|
+
overviews;
|
|
3635
|
+
/** A cached CRS value. */
|
|
3636
|
+
_crs;
|
|
3637
|
+
/** Cached TIFF tags that are pre-fetched when opening the GeoTIFF. */
|
|
3638
|
+
cachedTags;
|
|
3639
|
+
/** The data source used for fetching tile data.
|
|
3640
|
+
*
|
|
3641
|
+
* This is typically the raw source (e.g. HTTP or memory) rather than a
|
|
3642
|
+
* layered source with caching and chunking, to avoid unnecessary copying of
|
|
3643
|
+
* tile data through cache layers.
|
|
3644
|
+
*/
|
|
3645
|
+
dataSource;
|
|
3646
|
+
/** The underlying Tiff instance. */
|
|
3647
|
+
tiff;
|
|
3648
|
+
/** The primary (full-resolution) TiffImage. */
|
|
3649
|
+
image;
|
|
3650
|
+
/** The mask IFD of the full-resolution GeoTIFF, if any. */
|
|
3651
|
+
maskImage;
|
|
3652
|
+
/** The GeoKeyDirectory of the primary IFD. */
|
|
3653
|
+
gkd;
|
|
3654
|
+
/** Parsed GDALMetadata tag, if present. */
|
|
3655
|
+
gdalMetadata;
|
|
3656
|
+
/**
|
|
3657
|
+
* Internal: when true, log each `dataSource` fetch (image tile data and
|
|
3658
|
+
* mask tile data) to the console with offset/length and a `data`/`mask`
|
|
3659
|
+
* label. Enable via the `debug` option on {@link GeoTIFF.open} or
|
|
3660
|
+
* {@link GeoTIFF.fromUrl}. Read by the tile-fetch path; not part of the
|
|
3661
|
+
* public API surface.
|
|
3662
|
+
*
|
|
3663
|
+
* @internal
|
|
3664
|
+
*/
|
|
3665
|
+
_debug;
|
|
3666
|
+
constructor(t, n, r, o, i, s, a, l, c) {
|
|
3667
|
+
this.tiff = t, this.image = n, this.maskImage = r, this.gkd = o, this.overviews = i, this.cachedTags = s, this.dataSource = a, this.gdalMetadata = l, this._debug = c;
|
|
3668
|
+
}
|
|
3669
|
+
/**
|
|
3670
|
+
* Open a GeoTIFF from a @cogeotiff/core Source.
|
|
3671
|
+
*
|
|
3672
|
+
* This creates and initialises the underlying Tiff, then classifies IFDs.
|
|
3673
|
+
*
|
|
3674
|
+
* @param options.dataSource A source for fetching tile data. This is separate from the source used to construct the TIFF to allow for separate caching implementations.
|
|
3675
|
+
* @param options.headerSource The source used to construct the TIFF. This is typically a layered source with caching and chunking, to optimise access to TIFF tags and IFDs. Callers who want to control the initial read size should compose a `SourceChunk` of the desired block size; cogeotiff's default `defaultReadSize` (16 KiB) gets padded up by the chunking layer anyway.
|
|
3676
|
+
* @param options.signal An optional {@link AbortSignal} to cancel the header reads.
|
|
3677
|
+
* @param options.debug When true, the returned GeoTIFF logs each tile/mask data fetch to the console. Off by default.
|
|
3678
|
+
*/
|
|
3679
|
+
static async open(t) {
|
|
3680
|
+
const { dataSource: n, headerSource: r, signal: o, debug: i } = t, s = await new Z(r).init({ signal: o });
|
|
3681
|
+
return s.options = void 0, _.fromTiff(s, n, { signal: o, debug: i });
|
|
3682
|
+
}
|
|
3683
|
+
/**
|
|
3684
|
+
* Create a GeoTIFF from an already-initialised Tiff instance.
|
|
3685
|
+
*
|
|
3686
|
+
* All IFDs are walked; mask IFDs are matched to data IFDs by matching
|
|
3687
|
+
* (width, height). Overviews are sorted from finest to coarsest resolution.
|
|
3688
|
+
*
|
|
3689
|
+
* @param dataSource A source for fetching tile data. This is separate from the source used to construct the TIFF to allow for separate caching implementations.
|
|
3690
|
+
* @param options.signal An optional {@link AbortSignal} to cancel header tag reads.
|
|
3691
|
+
* @param options.debug When true, the returned GeoTIFF logs each tile/mask data fetch to the console.
|
|
3692
|
+
*/
|
|
3693
|
+
static async fromTiff(t, n, r = {}) {
|
|
3694
|
+
const { signal: o, debug: i = !1 } = r, s = t.images;
|
|
3695
|
+
if (s.length === 0)
|
|
3696
|
+
throw new Error("TIFF does not contain any IFDs");
|
|
3697
|
+
await Promise.all(s.map((b) => b.init(!0, { signal: o })));
|
|
3698
|
+
const a = s[0], l = ro(a), c = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
|
|
3699
|
+
for (let b = 1; b < s.length; b++) {
|
|
3700
|
+
const S = s[b], v = S.size, L = `${v.width},${v.height}`;
|
|
3701
|
+
lo(S) ? u.set(L, S) : c.set(L, S);
|
|
3702
|
+
}
|
|
3703
|
+
const h = `${a.size.width},${a.size.height}`, p = u.get(h) ?? null, d = Array.from(c.entries());
|
|
3704
|
+
d.sort((b, S) => {
|
|
3705
|
+
const v = b[1].size, L = S[1].size;
|
|
3706
|
+
return L.width * L.height - v.width * v.height;
|
|
3707
|
+
});
|
|
3708
|
+
const g = await no(a, { signal: o }), f = to(g.gdalMetadata, {
|
|
3709
|
+
count: g.samplesPerPixel
|
|
3710
|
+
}), y = new _(t, a, p, l, [], g, n, f, i), j = d.map(([b, S]) => {
|
|
3711
|
+
const v = u.get(b) ?? null;
|
|
3712
|
+
return new ao(y, l, S, v, g, n);
|
|
3713
|
+
});
|
|
3714
|
+
return y.overviews = j, y;
|
|
3715
|
+
}
|
|
3716
|
+
/**
|
|
3717
|
+
* Create a GeoTIFF from an ArrayBuffer containing the entire file.
|
|
3718
|
+
*
|
|
3719
|
+
* This is a convenience method that wraps the ArrayBuffer in a memory source
|
|
3720
|
+
* and calls {@link GeoTIFF.open}. For large files, consider using
|
|
3721
|
+
* {@link GeoTIFF.fromUrl} or {@link GeoTIFF.open} with a chunked HTTP source
|
|
3722
|
+
* to avoid loading the entire file into memory at once.
|
|
3723
|
+
*
|
|
3724
|
+
* @param input The ArrayBuffer containing the GeoTIFF file data.
|
|
3725
|
+
* @returns A Promise that resolves to a GeoTIFF instance.
|
|
3726
|
+
*/
|
|
3727
|
+
static async fromArrayBuffer(t) {
|
|
3728
|
+
const n = new xe("memory://input.tif", t);
|
|
3729
|
+
return await _.open({
|
|
3730
|
+
dataSource: n,
|
|
3731
|
+
headerSource: n
|
|
3732
|
+
});
|
|
3733
|
+
}
|
|
3734
|
+
/**
|
|
3735
|
+
* Create a new GeoTIFF from a URL.
|
|
3736
|
+
*
|
|
3737
|
+
* Wraps the HTTP source with a fixed-size block-aligned LRU cache tuned for
|
|
3738
|
+
* TIFF metadata. cogeotiff's lazy per-entry reads (for tile offsets, byte
|
|
3739
|
+
* counts, and other tag values) are served by the block cache; adjacent
|
|
3740
|
+
* entries within a single block hit one underlying request. Tile data reads
|
|
3741
|
+
* bypass the cache and go straight to the raw HTTP source.
|
|
3742
|
+
*
|
|
3743
|
+
* @param url The URL of the GeoTIFF to open.
|
|
3744
|
+
* @param options Optional parameters.
|
|
3745
|
+
* @param options.chunkSize Bytes per chunk for the header cache. Defaults to 64 KiB (matches geotiff.js's BlockedSource).
|
|
3746
|
+
* @param options.cacheSize Total cache size in bytes. Defaults to 8 MiB (~128 blocks at the default chunk size).
|
|
3747
|
+
* @param options.signal An optional {@link AbortSignal} to cancel the header reads.
|
|
3748
|
+
* @param options.debug When true, the returned GeoTIFF logs each tile/mask data fetch to the console with offset/length and a `data`/`mask` label. Off by default.
|
|
3749
|
+
* @returns A Promise that resolves to a GeoTIFF instance.
|
|
3750
|
+
*/
|
|
3751
|
+
static async fromUrl(t, { chunkSize: n = 64 * 1024, cacheSize: r = 8 * 1024 * 1024, signal: o, debug: i } = {}) {
|
|
3752
|
+
const s = new Y(t, {});
|
|
3753
|
+
s.metadata = { size: Number.POSITIVE_INFINITY };
|
|
3754
|
+
const a = new er(s, [
|
|
3755
|
+
new nr({ size: n }),
|
|
3756
|
+
new $n({ size: r })
|
|
3757
|
+
]);
|
|
3758
|
+
return await _.open({
|
|
3759
|
+
// Tile data reads bypass the header cache (raw source).
|
|
3760
|
+
dataSource: s,
|
|
3761
|
+
headerSource: a,
|
|
3762
|
+
signal: o,
|
|
3763
|
+
debug: i
|
|
3764
|
+
});
|
|
3765
|
+
}
|
|
3766
|
+
// ── Properties from the primary image ─────────────────────────────────
|
|
3767
|
+
/**
|
|
3768
|
+
* The CRS parsed from the GeoKeyDirectory.
|
|
3769
|
+
*
|
|
3770
|
+
* Returns an EPSG code (number) for EPSG-coded CRSes, or a PROJJSON object
|
|
3771
|
+
* for user-defined CRSes. The result is cached after the first access.
|
|
3772
|
+
*
|
|
3773
|
+
* See also {@link GeoTIFF.epsg} for the EPSG code directly from the TIFF tags.
|
|
3774
|
+
*/
|
|
3775
|
+
get crs() {
|
|
3776
|
+
return this._crs === void 0 && (this._crs = Fr(this.gkd)), this._crs;
|
|
3777
|
+
}
|
|
3778
|
+
/** Image width in pixels. */
|
|
3779
|
+
get width() {
|
|
3780
|
+
return this.image.size.width;
|
|
3781
|
+
}
|
|
3782
|
+
/** Image height in pixels. */
|
|
3783
|
+
get height() {
|
|
3784
|
+
return this.image.size.height;
|
|
3785
|
+
}
|
|
3786
|
+
/** The number of tiles in the x and y directions */
|
|
3787
|
+
get tileCount() {
|
|
3788
|
+
return this.image.tileCount;
|
|
3789
|
+
}
|
|
3790
|
+
/** Tile width in pixels. */
|
|
3791
|
+
get tileWidth() {
|
|
3792
|
+
return this.image.tileSize.width;
|
|
3793
|
+
}
|
|
3794
|
+
/** Tile height in pixels. */
|
|
3795
|
+
get tileHeight() {
|
|
3796
|
+
return this.image.tileSize.height;
|
|
3797
|
+
}
|
|
3798
|
+
/** The no data value, or null if not set. */
|
|
3799
|
+
get nodata() {
|
|
3800
|
+
return this.image.noData;
|
|
3801
|
+
}
|
|
3802
|
+
/** Whether the primary image is tiled. */
|
|
3803
|
+
get isTiled() {
|
|
3804
|
+
return this.image.isTiled();
|
|
3805
|
+
}
|
|
3806
|
+
/**
|
|
3807
|
+
* The pre-existing statistics for each band, if available.
|
|
3808
|
+
*
|
|
3809
|
+
* Extracted from the GDALMetadata TIFF tag; never computed on demand.
|
|
3810
|
+
* Keys are **1-based** band indices to match GDAL's convention.
|
|
3811
|
+
*
|
|
3812
|
+
* Returns `null` if no statistics are stored in the file.
|
|
3813
|
+
*/
|
|
3814
|
+
get storedStats() {
|
|
3815
|
+
const t = this.gdalMetadata?.bandStatistics;
|
|
3816
|
+
return t && t.size > 0 ? t : null;
|
|
3817
|
+
}
|
|
3818
|
+
/**
|
|
3819
|
+
* The offset for each band (0-indexed), defaulting to 0.
|
|
3820
|
+
*
|
|
3821
|
+
* Extracted from the GDALMetadata TIFF tag.
|
|
3822
|
+
*/
|
|
3823
|
+
get offsets() {
|
|
3824
|
+
return this.gdalMetadata?.offsets ?? Array(this.count).fill(0);
|
|
3825
|
+
}
|
|
3826
|
+
/**
|
|
3827
|
+
* The scale for each band (0-indexed), defaulting to 1.
|
|
3828
|
+
*
|
|
3829
|
+
* Extracted from the GDALMetadata TIFF tag.
|
|
3830
|
+
*/
|
|
3831
|
+
get scales() {
|
|
3832
|
+
return this.gdalMetadata?.scales ?? Array(this.count).fill(1);
|
|
3833
|
+
}
|
|
3834
|
+
/** Number of bands (samples per pixel). */
|
|
3835
|
+
get count() {
|
|
3836
|
+
return this.image.value(m.SamplesPerPixel) ?? 1;
|
|
3837
|
+
}
|
|
3838
|
+
/** Bounding box [minX, minY, maxX, maxY] in the CRS. */
|
|
3839
|
+
get bbox() {
|
|
3840
|
+
return this.image.bbox;
|
|
3841
|
+
}
|
|
3842
|
+
/**
|
|
3843
|
+
* Return the dataset's georeferencing transformation matrix.
|
|
3844
|
+
*/
|
|
3845
|
+
get transform() {
|
|
3846
|
+
const { modelPixelScale: t, modelTiepoint: n, modelTransformation: r } = this.cachedTags;
|
|
3847
|
+
return oo({
|
|
3848
|
+
modelTiepoint: n,
|
|
3849
|
+
modelPixelScale: t,
|
|
3850
|
+
modelTransformation: r,
|
|
3851
|
+
rasterType: this.gkd.rasterType
|
|
3852
|
+
});
|
|
3853
|
+
}
|
|
3854
|
+
// Mixins
|
|
3855
|
+
/** Fetch a single tile from the full-resolution image.
|
|
3856
|
+
*
|
|
3857
|
+
* @param x The tile column index (0-based).
|
|
3858
|
+
* @param y The tile row index (0-based).
|
|
3859
|
+
* @param options Optional parameters for fetching the tile.
|
|
3860
|
+
* @param options.boundless Whether to clip tiles that are partially outside the image bounds. When `true`, no clipping is applied and edge tiles are returned at the full nominal tile size. Defaults to `true`.
|
|
3861
|
+
* @param options.pool An optional {@link DecoderPool} for decoding the tile data. If not provided, a new decoder will be created for each tile.
|
|
3862
|
+
* @param options.signal An optional {@link AbortSignal} to cancel the fetch request.
|
|
3863
|
+
*/
|
|
3864
|
+
async fetchTile(t, n, r = {}) {
|
|
3865
|
+
return await yt(this, t, n, r);
|
|
3866
|
+
}
|
|
3867
|
+
/**
|
|
3868
|
+
* Fetch multiple tiles in parallel.
|
|
3869
|
+
*
|
|
3870
|
+
* A future implementation may coalesce contiguous byte ranges to reduce
|
|
3871
|
+
* the number of HTTP requests.
|
|
3872
|
+
*
|
|
3873
|
+
* @param xy - Array of `[x, y]` tile coordinates.
|
|
3874
|
+
* @param options - Optional parameters (same as {@link fetchTile}).
|
|
3875
|
+
* @returns Array of {@link Tile} objects in the same order as `xy`.
|
|
3876
|
+
*
|
|
3877
|
+
* @see {@link fetchTile} for single-tile fetching.
|
|
3878
|
+
*/
|
|
3879
|
+
async fetchTiles(t, n = {}) {
|
|
3880
|
+
return await Pt(this, t, n);
|
|
3881
|
+
}
|
|
3882
|
+
// Transform mixin
|
|
3883
|
+
/**
|
|
3884
|
+
* Get the (row, col) pixel index containing the geographic coordinate (x, y).
|
|
3885
|
+
*
|
|
3886
|
+
* @param x x coordinate in the CRS.
|
|
3887
|
+
* @param y y coordinate in the CRS.
|
|
3888
|
+
* @param op Rounding function applied to fractional pixel indices.
|
|
3889
|
+
* Defaults to Math.floor.
|
|
3890
|
+
* @returns [row, col] pixel indices.
|
|
3891
|
+
*/
|
|
3892
|
+
index(t, n, r = Math.floor) {
|
|
3893
|
+
return xt(this, t, n, r);
|
|
3894
|
+
}
|
|
3895
|
+
/**
|
|
3896
|
+
* Get the geographic (x, y) coordinate of the pixel at (row, col).
|
|
3897
|
+
*
|
|
3898
|
+
* @param row Pixel row.
|
|
3899
|
+
* @param col Pixel column.
|
|
3900
|
+
* @param offset Which part of the pixel to return. Defaults to "center".
|
|
3901
|
+
* @returns [x, y] in the CRS.
|
|
3902
|
+
*/
|
|
3903
|
+
xy(t, n, r = "center") {
|
|
3904
|
+
return Ot(this, t, n, r);
|
|
3905
|
+
}
|
|
3906
|
+
}
|
|
3907
|
+
function lo(e) {
|
|
3908
|
+
const t = e.value(m.SubFileType), n = e.value(m.Photometric);
|
|
3909
|
+
return t !== null && (t & $.Mask) !== 0 && n === R.Mask;
|
|
3910
|
+
}
|
|
3911
|
+
class co {
|
|
3912
|
+
worker;
|
|
3913
|
+
jobIdCounter = 0;
|
|
3914
|
+
jobs = /* @__PURE__ */ new Map();
|
|
3915
|
+
constructor(t) {
|
|
3916
|
+
this.worker = t, this.worker.addEventListener("message", (n) => this.onMessage(n));
|
|
3917
|
+
}
|
|
3918
|
+
get jobCount() {
|
|
3919
|
+
return this.jobs.size;
|
|
3920
|
+
}
|
|
3921
|
+
onMessage(t) {
|
|
3922
|
+
const { jobId: n, error: r, pixels: o } = t.data, i = this.jobs.get(n);
|
|
3923
|
+
this.jobs.delete(n), i && (r ? i.reject(new Error(r)) : i.resolve(o));
|
|
3924
|
+
}
|
|
3925
|
+
submitJob(t, n) {
|
|
3926
|
+
const r = this.jobIdCounter++;
|
|
3927
|
+
return new Promise((o, i) => {
|
|
3928
|
+
this.jobs.set(r, { resolve: o, reject: i }), this.worker.postMessage({ ...t, jobId: r }, { transfer: n });
|
|
3929
|
+
});
|
|
3930
|
+
}
|
|
3931
|
+
terminate() {
|
|
3932
|
+
this.worker.terminate();
|
|
3933
|
+
}
|
|
3934
|
+
}
|
|
3935
|
+
const uo = typeof navigator < "u" ? navigator.hardwareConcurrency ?? 2 : 2;
|
|
3936
|
+
class ho {
|
|
3937
|
+
workerWrappers;
|
|
3938
|
+
constructor(t = {}) {
|
|
3939
|
+
const { size: n = uo, createWorker: r } = t;
|
|
3940
|
+
if (this.workerWrappers = [], r && n > 0)
|
|
3941
|
+
for (let o = 0; o < n; o++)
|
|
3942
|
+
this.workerWrappers.push(new co(r()));
|
|
3943
|
+
}
|
|
3944
|
+
/** True when workers are available for off-main-thread decoding. */
|
|
3945
|
+
get hasWorkers() {
|
|
3946
|
+
return this.workerWrappers.length > 0;
|
|
3947
|
+
}
|
|
3948
|
+
/**
|
|
3949
|
+
* Decode a compressed tile buffer.
|
|
3950
|
+
*
|
|
3951
|
+
* When workers are available, the compressed `bytes` buffer is transferred
|
|
3952
|
+
* zero-copy to the least-loaded worker. The returned `DecodedPixels` typed
|
|
3953
|
+
* array buffers are transferred back to the main thread.
|
|
3954
|
+
*
|
|
3955
|
+
* When no workers are available, decoding runs on the main thread via the
|
|
3956
|
+
* normal `decode()` path.
|
|
3957
|
+
*/
|
|
3958
|
+
async decode(t, n, r) {
|
|
3959
|
+
if (!this.hasWorkers)
|
|
3960
|
+
return je(t, n, r);
|
|
3961
|
+
const o = this.leastLoaded(), i = {
|
|
3962
|
+
compression: n,
|
|
3963
|
+
metadata: r,
|
|
3964
|
+
buffer: t
|
|
3965
|
+
};
|
|
3966
|
+
return await o.submitJob(i, [t]);
|
|
3967
|
+
}
|
|
3968
|
+
/** Terminate all workers and release resources. */
|
|
3969
|
+
destroy() {
|
|
3970
|
+
for (const t of this.workerWrappers)
|
|
3971
|
+
t.terminate();
|
|
3972
|
+
this.workerWrappers.length = 0;
|
|
3973
|
+
}
|
|
3974
|
+
leastLoaded() {
|
|
3975
|
+
let t = this.workerWrappers[0];
|
|
3976
|
+
for (let n = 1; n < this.workerWrappers.length; n++)
|
|
3977
|
+
this.workerWrappers[n].jobCount < t.jobCount && (t = this.workerWrappers[n]);
|
|
3978
|
+
return t;
|
|
3979
|
+
}
|
|
3980
|
+
}
|
|
3981
|
+
let oe = null;
|
|
3982
|
+
function po() {
|
|
3983
|
+
return oe !== null || (oe = new ho({
|
|
3984
|
+
createWorker: () => new Worker(new URL(
|
|
3985
|
+
/* @vite-ignore */
|
|
3986
|
+
"/assets/worker-DtIrTJB7.js",
|
|
3987
|
+
import.meta.url
|
|
3988
|
+
), { type: "module" })
|
|
3989
|
+
})), oe;
|
|
3990
|
+
}
|
|
3991
|
+
function mo(e) {
|
|
3992
|
+
const { height: t, width: n } = e;
|
|
3993
|
+
if (e.layout === "band-separate")
|
|
3994
|
+
throw new Error("Band-separate images not yet implemented.");
|
|
3995
|
+
if (e.data.length === t * n * 4)
|
|
3996
|
+
return e;
|
|
3997
|
+
if (e.data.length === t * n * 3) {
|
|
3998
|
+
const r = e.data.length / 3 * 4, o = e.data instanceof Uint16Array, i = o ? new Uint16Array(r) : new Uint8ClampedArray(r), s = o ? 65535 : 255;
|
|
3999
|
+
for (let a = 0; a < e.data.length / 3; ++a)
|
|
4000
|
+
i[a * 4] = e.data[a * 3], i[a * 4 + 1] = e.data[a * 3 + 1], i[a * 4 + 2] = e.data[a * 3 + 2], i[a * 4 + 3] = s;
|
|
4001
|
+
return {
|
|
4002
|
+
...e,
|
|
4003
|
+
count: 4,
|
|
4004
|
+
data: i
|
|
4005
|
+
};
|
|
4006
|
+
} else
|
|
4007
|
+
throw new Error(`Unexpected number of channels in raster data: ${e.data.length / (t * n)}`);
|
|
4008
|
+
}
|
|
4009
|
+
async function go(e) {
|
|
4010
|
+
return typeof e == "string" || e instanceof URL ? await _.fromUrl(e) : e instanceof ArrayBuffer ? await _.fromArrayBuffer(e) : e;
|
|
4011
|
+
}
|
|
4012
|
+
function fo(e, t) {
|
|
4013
|
+
const [n, r, o, i] = e.bbox, s = [
|
|
4014
|
+
t.forward([n, r]),
|
|
4015
|
+
// bottom-left
|
|
4016
|
+
t.forward([o, r]),
|
|
4017
|
+
// bottom-right
|
|
4018
|
+
t.forward([o, i]),
|
|
4019
|
+
// top-right
|
|
4020
|
+
t.forward([n, i])
|
|
4021
|
+
// top-left
|
|
4022
|
+
], a = s.map((d) => d[0]), l = s.map((d) => d[1]), c = Math.min(...a), u = Math.min(...l), h = Math.max(...a), p = Math.max(...l);
|
|
4023
|
+
return { west: c, south: u, east: h, north: p };
|
|
4024
|
+
}
|
|
4025
|
+
const yo = (
|
|
4026
|
+
/* glsl */
|
|
4027
|
+
`
|
|
4028
|
+
vec3 black_zero_to_rgb(float value) {
|
|
4029
|
+
return vec3(value, value, value);
|
|
4030
|
+
}
|
|
4031
|
+
`
|
|
4032
|
+
), wo = {
|
|
4033
|
+
name: "black-is-zero",
|
|
4034
|
+
inject: {
|
|
4035
|
+
"fs:#decl": yo,
|
|
4036
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4037
|
+
/* glsl */
|
|
4038
|
+
`
|
|
4039
|
+
color.rgb = black_zero_to_rgb(color.r);
|
|
4040
|
+
`
|
|
4041
|
+
)
|
|
4042
|
+
}
|
|
4043
|
+
}, Po = (
|
|
4044
|
+
/* glsl */
|
|
4045
|
+
`
|
|
4046
|
+
const vec3 D65 = vec3(
|
|
4047
|
+
0.95047, // Xn
|
|
4048
|
+
1.00000, // Yn
|
|
4049
|
+
1.08883 // Zn
|
|
4050
|
+
);
|
|
4051
|
+
|
|
4052
|
+
vec3 cielabToRgb(vec3 labTex) {
|
|
4053
|
+
// labTex in [0,1] from RGB8 texture
|
|
4054
|
+
float L = labTex.r * 255.0;
|
|
4055
|
+
float a = (labTex.g - 0.5) * 255.0;
|
|
4056
|
+
float b = (labTex.b - 0.5) * 255.0;
|
|
4057
|
+
|
|
4058
|
+
float y = (L + 16.0) / 116.0;
|
|
4059
|
+
float x = (a / 500.0) + y;
|
|
4060
|
+
float z = y - (b / 200.0);
|
|
4061
|
+
|
|
4062
|
+
vec3 xyz;
|
|
4063
|
+
vec3 v = vec3(x, y, z);
|
|
4064
|
+
vec3 v3 = v * v * v;
|
|
4065
|
+
|
|
4066
|
+
xyz = D65 * mix(
|
|
4067
|
+
(v - 16.0 / 116.0) / 7.787,
|
|
4068
|
+
v3,
|
|
4069
|
+
step(0.008856, v3)
|
|
4070
|
+
);
|
|
4071
|
+
|
|
4072
|
+
vec3 rgb = mat3(
|
|
4073
|
+
3.2406, -1.5372, -0.4986,
|
|
4074
|
+
-0.9689, 1.8758, 0.0415,
|
|
4075
|
+
0.0557, -0.2040, 1.0570
|
|
4076
|
+
) * xyz;
|
|
4077
|
+
|
|
4078
|
+
// sRGB gamma
|
|
4079
|
+
rgb = mix(
|
|
4080
|
+
12.92 * rgb,
|
|
4081
|
+
1.055 * pow(rgb, vec3(1.0 / 2.4)) - 0.055,
|
|
4082
|
+
step(0.0031308, rgb)
|
|
4083
|
+
);
|
|
4084
|
+
|
|
4085
|
+
return clamp(rgb, 0.0, 1.0);
|
|
4086
|
+
}
|
|
4087
|
+
`
|
|
4088
|
+
), bo = {
|
|
4089
|
+
name: "cielab-to-rgb",
|
|
4090
|
+
inject: {
|
|
4091
|
+
"fs:#decl": Po,
|
|
4092
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4093
|
+
/* glsl */
|
|
4094
|
+
`
|
|
4095
|
+
color.rgb = cielabToRgb(color);
|
|
4096
|
+
`
|
|
4097
|
+
)
|
|
4098
|
+
}
|
|
4099
|
+
}, vo = (
|
|
4100
|
+
/* glsl */
|
|
4101
|
+
`
|
|
4102
|
+
vec3 cmykToRgb(vec4 cmyk) {
|
|
4103
|
+
// cmyk in [0.0, 1.0]
|
|
4104
|
+
float invK = 1.0 - cmyk.a;
|
|
4105
|
+
|
|
4106
|
+
return vec3(
|
|
4107
|
+
(1.0 - cmyk.r) * invK,
|
|
4108
|
+
(1.0 - cmyk.g) * invK,
|
|
4109
|
+
(1.0 - cmyk.b) * invK
|
|
4110
|
+
);
|
|
4111
|
+
}
|
|
4112
|
+
`
|
|
4113
|
+
), So = {
|
|
4114
|
+
name: "cmyk-to-rgb",
|
|
4115
|
+
inject: {
|
|
4116
|
+
"fs:#decl": vo,
|
|
4117
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4118
|
+
/* glsl */
|
|
4119
|
+
`
|
|
4120
|
+
color.rgb = cmykToRgb(color);
|
|
4121
|
+
`
|
|
4122
|
+
)
|
|
4123
|
+
}
|
|
4124
|
+
}, Lo = (
|
|
4125
|
+
/* glsl */
|
|
4126
|
+
`
|
|
4127
|
+
vec3 white_zero_to_rgb(float value) {
|
|
4128
|
+
return vec3(1.0 - value, 1.0 - value, 1.0 - value);
|
|
4129
|
+
}
|
|
4130
|
+
`
|
|
4131
|
+
), Co = {
|
|
4132
|
+
name: "white-is-zero",
|
|
4133
|
+
inject: {
|
|
4134
|
+
"fs:#decl": Lo,
|
|
4135
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4136
|
+
/* glsl */
|
|
4137
|
+
`
|
|
4138
|
+
color.rgb = white_zero_to_rgb(color.r);
|
|
4139
|
+
`
|
|
4140
|
+
)
|
|
4141
|
+
}
|
|
4142
|
+
}, T = "colormap", At = {
|
|
4143
|
+
name: T,
|
|
4144
|
+
fs: `uniform ${T}Uniforms {
|
|
4145
|
+
int colormapIndex;
|
|
4146
|
+
float reversed;
|
|
4147
|
+
} ${T};
|
|
4148
|
+
`,
|
|
4149
|
+
inject: {
|
|
4150
|
+
"fs:#decl": `precision highp sampler2DArray;
|
|
4151
|
+
uniform sampler2DArray colormapTexture;
|
|
4152
|
+
`,
|
|
4153
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4154
|
+
/* glsl */
|
|
4155
|
+
`
|
|
4156
|
+
float idx = mix(color.r, 1.0 - color.r, ${T}.reversed);
|
|
4157
|
+
color = texture(
|
|
4158
|
+
colormapTexture,
|
|
4159
|
+
vec3(idx, 0.5, float(${T}.colormapIndex))
|
|
4160
|
+
);
|
|
4161
|
+
`
|
|
4162
|
+
)
|
|
4163
|
+
},
|
|
4164
|
+
uniformTypes: {
|
|
4165
|
+
colormapIndex: "i32",
|
|
4166
|
+
reversed: "f32"
|
|
4167
|
+
},
|
|
4168
|
+
getUniforms: (e) => ({
|
|
4169
|
+
colormapTexture: e.colormapTexture,
|
|
4170
|
+
colormapIndex: e.colormapIndex ?? 0,
|
|
4171
|
+
reversed: e.reversed ?? !1
|
|
4172
|
+
})
|
|
4173
|
+
}, he = {
|
|
4174
|
+
accent: 0,
|
|
4175
|
+
afmhot: 1,
|
|
4176
|
+
algae: 2,
|
|
4177
|
+
amp: 3,
|
|
4178
|
+
autumn: 4,
|
|
4179
|
+
balance: 5,
|
|
4180
|
+
binary: 6,
|
|
4181
|
+
blues: 7,
|
|
4182
|
+
bone: 8,
|
|
4183
|
+
brbg: 9,
|
|
4184
|
+
brg: 10,
|
|
4185
|
+
bugn: 11,
|
|
4186
|
+
bupu: 12,
|
|
4187
|
+
bwr: 13,
|
|
4188
|
+
cfastie: 14,
|
|
4189
|
+
cividis: 15,
|
|
4190
|
+
cmrmap: 16,
|
|
4191
|
+
cool: 17,
|
|
4192
|
+
coolwarm: 18,
|
|
4193
|
+
copper: 19,
|
|
4194
|
+
cubehelix: 20,
|
|
4195
|
+
curl: 21,
|
|
4196
|
+
dark2: 22,
|
|
4197
|
+
deep: 23,
|
|
4198
|
+
delta: 24,
|
|
4199
|
+
dense: 25,
|
|
4200
|
+
diff: 26,
|
|
4201
|
+
flag: 27,
|
|
4202
|
+
gist_earth: 28,
|
|
4203
|
+
gist_gray: 29,
|
|
4204
|
+
gist_heat: 30,
|
|
4205
|
+
gist_ncar: 31,
|
|
4206
|
+
gist_rainbow: 32,
|
|
4207
|
+
gist_stern: 33,
|
|
4208
|
+
gist_yarg: 34,
|
|
4209
|
+
gnbu: 35,
|
|
4210
|
+
gnuplot: 36,
|
|
4211
|
+
gnuplot2: 37,
|
|
4212
|
+
gray: 38,
|
|
4213
|
+
greens: 39,
|
|
4214
|
+
greys: 40,
|
|
4215
|
+
haline: 41,
|
|
4216
|
+
hot: 42,
|
|
4217
|
+
hsv: 43,
|
|
4218
|
+
ice: 44,
|
|
4219
|
+
inferno: 45,
|
|
4220
|
+
jet: 46,
|
|
4221
|
+
magma: 47,
|
|
4222
|
+
matter: 48,
|
|
4223
|
+
nipy_spectral: 49,
|
|
4224
|
+
ocean: 50,
|
|
4225
|
+
oranges: 51,
|
|
4226
|
+
orrd: 52,
|
|
4227
|
+
oxy: 53,
|
|
4228
|
+
paired: 54,
|
|
4229
|
+
pastel1: 55,
|
|
4230
|
+
pastel2: 56,
|
|
4231
|
+
phase: 57,
|
|
4232
|
+
pink: 58,
|
|
4233
|
+
piyg: 59,
|
|
4234
|
+
plasma: 60,
|
|
4235
|
+
prgn: 61,
|
|
4236
|
+
prism: 62,
|
|
4237
|
+
pubu: 63,
|
|
4238
|
+
pubugn: 64,
|
|
4239
|
+
puor: 65,
|
|
4240
|
+
purd: 66,
|
|
4241
|
+
purples: 67,
|
|
4242
|
+
rain: 68,
|
|
4243
|
+
rainbow: 69,
|
|
4244
|
+
rdbu: 70,
|
|
4245
|
+
rdgy: 71,
|
|
4246
|
+
rdpu: 72,
|
|
4247
|
+
rdylbu: 73,
|
|
4248
|
+
rdylgn: 74,
|
|
4249
|
+
reds: 75,
|
|
4250
|
+
rplumbo: 76,
|
|
4251
|
+
schwarzwald: 77,
|
|
4252
|
+
seismic: 78,
|
|
4253
|
+
set1: 79,
|
|
4254
|
+
set2: 80,
|
|
4255
|
+
set3: 81,
|
|
4256
|
+
solar: 82,
|
|
4257
|
+
spectral: 83,
|
|
4258
|
+
speed: 84,
|
|
4259
|
+
spring: 85,
|
|
4260
|
+
summer: 86,
|
|
4261
|
+
tab10: 87,
|
|
4262
|
+
tab20: 88,
|
|
4263
|
+
tab20b: 89,
|
|
4264
|
+
tab20c: 90,
|
|
4265
|
+
tarn: 91,
|
|
4266
|
+
tempo: 92,
|
|
4267
|
+
terrain: 93,
|
|
4268
|
+
thermal: 94,
|
|
4269
|
+
topo: 95,
|
|
4270
|
+
turbid: 96,
|
|
4271
|
+
turbo: 97,
|
|
4272
|
+
twilight: 98,
|
|
4273
|
+
twilight_shifted: 99,
|
|
4274
|
+
viridis: 100,
|
|
4275
|
+
winter: 101,
|
|
4276
|
+
wistia: 102,
|
|
4277
|
+
ylgn: 103,
|
|
4278
|
+
ylgnbu: 104,
|
|
4279
|
+
ylorbr: 105,
|
|
4280
|
+
ylorrd: 106
|
|
4281
|
+
};
|
|
4282
|
+
function jo(e, t) {
|
|
4283
|
+
if (t.width !== 256)
|
|
4284
|
+
throw new Error(`Expected a 256-pixel-wide colormap sprite, got width ${t.width}.`);
|
|
4285
|
+
const n = new Uint8Array(t.data.buffer, t.data.byteOffset, t.data.byteLength);
|
|
4286
|
+
return e.createTexture({
|
|
4287
|
+
dimension: "2d-array",
|
|
4288
|
+
format: "rgba8unorm",
|
|
4289
|
+
width: 256,
|
|
4290
|
+
height: 1,
|
|
4291
|
+
depth: t.height,
|
|
4292
|
+
data: n,
|
|
4293
|
+
mipLevels: 1,
|
|
4294
|
+
sampler: {
|
|
4295
|
+
minFilter: "linear",
|
|
4296
|
+
magFilter: "linear",
|
|
4297
|
+
// Clamp in every axis so an out-of-range colormapIndex yields an
|
|
4298
|
+
// edge color rather than wrapping to an unrelated colormap.
|
|
4299
|
+
addressModeU: "clamp-to-edge",
|
|
4300
|
+
addressModeV: "clamp-to-edge",
|
|
4301
|
+
addressModeW: "clamp-to-edge"
|
|
4302
|
+
}
|
|
4303
|
+
});
|
|
4304
|
+
}
|
|
4305
|
+
async function xo(e) {
|
|
4306
|
+
const t = await Oo(e);
|
|
4307
|
+
try {
|
|
4308
|
+
return Ao(t);
|
|
4309
|
+
} finally {
|
|
4310
|
+
t.close();
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
async function Oo(e) {
|
|
4314
|
+
if (e instanceof ImageBitmap)
|
|
4315
|
+
return e;
|
|
4316
|
+
const t = new Blob([e]);
|
|
4317
|
+
return createImageBitmap(t);
|
|
4318
|
+
}
|
|
4319
|
+
function Ao(e) {
|
|
4320
|
+
const n = new OffscreenCanvas(e.width, e.height).getContext("2d");
|
|
4321
|
+
if (!n)
|
|
4322
|
+
throw new Error("Failed to obtain 2D context for decoding the colormap sprite.");
|
|
4323
|
+
return n.drawImage(e, 0, 0), n.getImageData(0, 0, e.width, e.height);
|
|
4324
|
+
}
|
|
4325
|
+
const ve = "nodata", Eo = `uniform ${ve}Uniforms {
|
|
4326
|
+
float value;
|
|
4327
|
+
} ${ve};
|
|
4328
|
+
`, Et = {
|
|
4329
|
+
name: ve,
|
|
4330
|
+
fs: Eo,
|
|
4331
|
+
inject: {
|
|
4332
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4333
|
+
/* glsl */
|
|
4334
|
+
`
|
|
4335
|
+
if (color.r == nodata.value) {
|
|
4336
|
+
discard;
|
|
4337
|
+
}
|
|
4338
|
+
`
|
|
4339
|
+
)
|
|
4340
|
+
},
|
|
4341
|
+
uniformTypes: {
|
|
4342
|
+
value: "f32"
|
|
4343
|
+
},
|
|
4344
|
+
getUniforms: (e) => ({
|
|
4345
|
+
value: e.value
|
|
4346
|
+
})
|
|
4347
|
+
}, H = "linearRescale", Io = {
|
|
4348
|
+
name: H,
|
|
4349
|
+
fs: `uniform ${H}Uniforms {
|
|
4350
|
+
float rescaleMin;
|
|
4351
|
+
float rescaleMax;
|
|
4352
|
+
} ${H};
|
|
4353
|
+
`,
|
|
4354
|
+
inject: {
|
|
4355
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4356
|
+
/* glsl */
|
|
4357
|
+
`
|
|
4358
|
+
color.rgb = clamp((color.rgb - ${H}.rescaleMin) / (${H}.rescaleMax - ${H}.rescaleMin), 0.0, 1.0);
|
|
4359
|
+
`
|
|
4360
|
+
)
|
|
4361
|
+
},
|
|
4362
|
+
uniformTypes: {
|
|
4363
|
+
rescaleMin: "f32",
|
|
4364
|
+
rescaleMax: "f32"
|
|
4365
|
+
},
|
|
4366
|
+
getUniforms: (e) => ({
|
|
4367
|
+
rescaleMin: e.rescaleMin ?? 0,
|
|
4368
|
+
rescaleMax: e.rescaleMax ?? 1
|
|
4369
|
+
})
|
|
4370
|
+
}, Mo = {
|
|
4371
|
+
name: "mask-texture",
|
|
4372
|
+
inject: {
|
|
4373
|
+
"fs:#decl": "uniform sampler2D maskTexture;",
|
|
4374
|
+
"fs:DECKGL_FILTER_COLOR": (
|
|
4375
|
+
/* glsl */
|
|
4376
|
+
`
|
|
4377
|
+
float maskValue = texture(maskTexture, geometry.uv).r;
|
|
4378
|
+
if (maskValue == 0.0) {
|
|
4379
|
+
discard;
|
|
4380
|
+
}
|
|
4381
|
+
`
|
|
4382
|
+
)
|
|
4383
|
+
},
|
|
4384
|
+
getUniforms: (e) => ({
|
|
4385
|
+
maskTexture: e.maskTexture
|
|
4386
|
+
})
|
|
4387
|
+
};
|
|
4388
|
+
function Ro(e, t, n) {
|
|
4389
|
+
const r = zo(e), o = Fo(t), i = Do(n), s = `${r}:${i}:${o}`, a = No[s];
|
|
4390
|
+
if (!a)
|
|
4391
|
+
throw new Error(`Unsupported texture format for SamplesPerPixel=${e}, BitsPerSample=${t}, SampleFormat=${n}`);
|
|
4392
|
+
return a;
|
|
4393
|
+
}
|
|
4394
|
+
function zo(e) {
|
|
4395
|
+
if (e === 1 || e === 2 || e === 3 || e === 4)
|
|
4396
|
+
return e;
|
|
4397
|
+
throw new Error(`Unsupported SamplesPerPixel ${e}. Only 1, 2, 3, or 4 are supported.`);
|
|
4398
|
+
}
|
|
4399
|
+
function Fo(e) {
|
|
4400
|
+
const t = e[0];
|
|
4401
|
+
for (let n = 1; n < e.length; n++)
|
|
4402
|
+
if (e[n] !== t)
|
|
4403
|
+
throw new Error(`Unsupported varying BitsPerSample ${e}. All samples must have the same bit width.`);
|
|
4404
|
+
if (t !== 8 && t !== 16 && t !== 32)
|
|
4405
|
+
throw new Error(`Unsupported BitsPerSample ${t}. Only 8, 16, or 32 are supported.`);
|
|
4406
|
+
return t;
|
|
4407
|
+
}
|
|
4408
|
+
function Do(e) {
|
|
4409
|
+
const t = e[0];
|
|
4410
|
+
for (let n = 1; n < e.length; n++)
|
|
4411
|
+
if (e[n] !== t)
|
|
4412
|
+
throw new Error(`Unsupported varying SampleFormat ${e}. All samples must have the same format.`);
|
|
4413
|
+
switch (t) {
|
|
4414
|
+
case F.Uint:
|
|
4415
|
+
return "unorm";
|
|
4416
|
+
case F.Int:
|
|
4417
|
+
return "sint";
|
|
4418
|
+
case F.Float:
|
|
4419
|
+
return "float";
|
|
4420
|
+
default:
|
|
4421
|
+
throw new Error(`Unsupported SampleFormat ${e}`);
|
|
4422
|
+
}
|
|
4423
|
+
}
|
|
4424
|
+
const No = {
|
|
4425
|
+
// 1 byte per pixel
|
|
4426
|
+
"1:sint:8": "r8sint",
|
|
4427
|
+
"1:uint:8": "r8uint",
|
|
4428
|
+
"1:unorm:8": "r8unorm",
|
|
4429
|
+
// 2 bytes per pixel (one channel)
|
|
4430
|
+
"1:float:16": "r16float",
|
|
4431
|
+
"1:sint:16": "r16sint",
|
|
4432
|
+
"1:uint:16": "r16uint",
|
|
4433
|
+
"1:unorm:16": "r16unorm",
|
|
4434
|
+
// 2 bytes per pixel (two channels)
|
|
4435
|
+
"2:sint:8": "rg8sint",
|
|
4436
|
+
"2:uint:8": "rg8uint",
|
|
4437
|
+
"2:unorm:8": "rg8unorm",
|
|
4438
|
+
// 4 bytes per pixel (one channel)
|
|
4439
|
+
"1:float:32": "r32float",
|
|
4440
|
+
"1:sint:32": "r32sint",
|
|
4441
|
+
"1:uint:32": "r32uint",
|
|
4442
|
+
// 4 bytes per pixel (two channels)
|
|
4443
|
+
"2:float:16": "rg16float",
|
|
4444
|
+
"2:sint:16": "rg16sint",
|
|
4445
|
+
"2:uint:16": "rg16uint",
|
|
4446
|
+
"2:unorm:16": "rg16unorm",
|
|
4447
|
+
// 4 bytes per pixel (four channels)
|
|
4448
|
+
"4:sint:8": "rgba8sint",
|
|
4449
|
+
"4:uint:8": "rgba8uint",
|
|
4450
|
+
"4:unorm:8": "rgba8unorm",
|
|
4451
|
+
// 6 bytes per pixel (three channels)
|
|
4452
|
+
// Note: this is supported on WebGL2 but not supported on WebGPU
|
|
4453
|
+
// I expect actual switch to WebGPU to be quite a ways off still
|
|
4454
|
+
"3:uint:16": "rgb16unorm-webgl",
|
|
4455
|
+
// 8 bytes per pixel (two channels)
|
|
4456
|
+
"2:float:32": "rg32float",
|
|
4457
|
+
"2:sint:32": "rg32sint",
|
|
4458
|
+
"2:uint:32": "rg32uint",
|
|
4459
|
+
// 8 bytes per pixel (four channels)
|
|
4460
|
+
"4:float:16": "rgba16float",
|
|
4461
|
+
"4:sint:16": "rgba16sint",
|
|
4462
|
+
"4:uint:16": "rgba16uint",
|
|
4463
|
+
"4:unorm:16": "rgba16unorm",
|
|
4464
|
+
// 12 bytes per pixel (three channels)
|
|
4465
|
+
"3:float:32": "rgb32float-webgl",
|
|
4466
|
+
// 16 bytes per pixel (four channels)
|
|
4467
|
+
"4:float:32": "rgba32float",
|
|
4468
|
+
"4:sint:32": "rgba32sint",
|
|
4469
|
+
"4:uint:32": "rgba32uint"
|
|
4470
|
+
};
|
|
4471
|
+
function Uo(e, t) {
|
|
4472
|
+
const { sampleFormat: n } = e.cachedTags;
|
|
4473
|
+
if (n === null)
|
|
4474
|
+
throw new Error("SampleFormat tag is required to infer render pipeline");
|
|
4475
|
+
switch (n[0]) {
|
|
4476
|
+
// Unsigned integers
|
|
4477
|
+
case F.Uint:
|
|
4478
|
+
return Bo(e, t);
|
|
4479
|
+
}
|
|
4480
|
+
throw new Error(`Inferring render pipeline for non-unsigned integers not yet supported. Found SampleFormat: ${n}`);
|
|
4481
|
+
}
|
|
4482
|
+
function Bo(e, t) {
|
|
4483
|
+
const { bitsPerSample: n, colorMap: r, photometric: o, sampleFormat: i, samplesPerPixel: s, nodata: a } = e.cachedTags, l = [
|
|
4484
|
+
{
|
|
4485
|
+
module: Se,
|
|
4486
|
+
props: {
|
|
4487
|
+
textureName: (d) => d.texture
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
];
|
|
4491
|
+
if (a !== null) {
|
|
4492
|
+
const d = 2 ** n[0] - 1, g = a / d;
|
|
4493
|
+
l.push({
|
|
4494
|
+
module: Et,
|
|
4495
|
+
props: { value: g }
|
|
4496
|
+
});
|
|
4497
|
+
}
|
|
4498
|
+
e.maskImage !== null && l.push({
|
|
4499
|
+
module: Mo,
|
|
4500
|
+
props: {
|
|
4501
|
+
// TODO: how to handle if mask failed to load and is undefined here
|
|
4502
|
+
maskTexture: (d) => d.mask
|
|
4503
|
+
}
|
|
4504
|
+
});
|
|
4505
|
+
const c = Go({
|
|
4506
|
+
count: s,
|
|
4507
|
+
photometric: o,
|
|
4508
|
+
device: t,
|
|
4509
|
+
colorMap: r
|
|
4510
|
+
});
|
|
4511
|
+
c && l.push(c);
|
|
4512
|
+
const u = o === R.Palette ? {
|
|
4513
|
+
magFilter: "nearest",
|
|
4514
|
+
minFilter: "nearest"
|
|
4515
|
+
} : {
|
|
4516
|
+
magFilter: "linear",
|
|
4517
|
+
minFilter: "linear"
|
|
4518
|
+
};
|
|
4519
|
+
return { getTileData: async (d, g) => {
|
|
4520
|
+
const { device: f, x: y, y: j, signal: b, pool: S } = g, v = await d.fetchTile(y, j, {
|
|
4521
|
+
boundless: !1,
|
|
4522
|
+
pool: S,
|
|
4523
|
+
signal: b
|
|
4524
|
+
});
|
|
4525
|
+
let { array: L } = v;
|
|
4526
|
+
const { width: E, height: M, mask: z } = L;
|
|
4527
|
+
let I = s;
|
|
4528
|
+
if (s === 3 && (L = mo(L), I = 4), L.layout === "band-separate")
|
|
4529
|
+
throw new Error("Band-separate images not yet implemented.");
|
|
4530
|
+
const J = Ro(
|
|
4531
|
+
// Add one sample for added alpha channel
|
|
4532
|
+
I,
|
|
4533
|
+
n,
|
|
4534
|
+
i
|
|
4535
|
+
);
|
|
4536
|
+
let q = L.data.byteLength;
|
|
4537
|
+
const te = f.createTexture({
|
|
4538
|
+
data: L.data,
|
|
4539
|
+
format: J,
|
|
4540
|
+
width: E,
|
|
4541
|
+
height: M,
|
|
4542
|
+
sampler: u
|
|
4543
|
+
});
|
|
4544
|
+
let ne;
|
|
4545
|
+
return z !== null && (ne = f.createTexture({
|
|
4546
|
+
data: z,
|
|
4547
|
+
// Single-channel 8-bit texture for the mask
|
|
4548
|
+
format: "r8unorm",
|
|
4549
|
+
width: E,
|
|
4550
|
+
height: M,
|
|
4551
|
+
// Use nearest filtering for the mask to avoid interpolated edges/halos
|
|
4552
|
+
sampler: {
|
|
4553
|
+
minFilter: "nearest",
|
|
4554
|
+
magFilter: "nearest"
|
|
4555
|
+
}
|
|
4556
|
+
}), q += z.byteLength), {
|
|
4557
|
+
texture: te,
|
|
4558
|
+
mask: ne,
|
|
4559
|
+
byteLength: q,
|
|
4560
|
+
height: L.height,
|
|
4561
|
+
width: L.width
|
|
4562
|
+
};
|
|
4563
|
+
}, renderTile: (d) => ({
|
|
4564
|
+
renderPipeline: l.map((g, f) => Ko(g, d))
|
|
4565
|
+
}) };
|
|
4566
|
+
}
|
|
4567
|
+
function Go({ count: e, colorMap: t, device: n, photometric: r }) {
|
|
4568
|
+
if (e === 3 || e === 4)
|
|
4569
|
+
return null;
|
|
4570
|
+
switch (r) {
|
|
4571
|
+
case R.MinIsWhite:
|
|
4572
|
+
return {
|
|
4573
|
+
module: Co
|
|
4574
|
+
};
|
|
4575
|
+
case R.MinIsBlack:
|
|
4576
|
+
return {
|
|
4577
|
+
module: wo
|
|
4578
|
+
};
|
|
4579
|
+
case R.Rgb:
|
|
4580
|
+
return null;
|
|
4581
|
+
case R.Palette: {
|
|
4582
|
+
if (!t)
|
|
4583
|
+
throw new Error("ColorMap is required for PhotometricInterpretation Palette");
|
|
4584
|
+
const { data: o, width: i, height: s } = En(t), a = n.createTexture({
|
|
4585
|
+
dimension: "2d-array",
|
|
4586
|
+
data: o,
|
|
4587
|
+
format: "rgba8unorm",
|
|
4588
|
+
width: i,
|
|
4589
|
+
height: s,
|
|
4590
|
+
depth: 1,
|
|
4591
|
+
mipLevels: 1,
|
|
4592
|
+
sampler: {
|
|
4593
|
+
minFilter: "nearest",
|
|
4594
|
+
magFilter: "nearest",
|
|
4595
|
+
addressModeU: "clamp-to-edge",
|
|
4596
|
+
addressModeV: "clamp-to-edge",
|
|
4597
|
+
addressModeW: "clamp-to-edge"
|
|
4598
|
+
}
|
|
4599
|
+
});
|
|
4600
|
+
return {
|
|
4601
|
+
module: At,
|
|
4602
|
+
props: {
|
|
4603
|
+
colormapTexture: a
|
|
4604
|
+
}
|
|
4605
|
+
};
|
|
4606
|
+
}
|
|
4607
|
+
// Not sure why cogeotiff calls this "Separated", but it means CMYK
|
|
4608
|
+
case R.Separated:
|
|
4609
|
+
return {
|
|
4610
|
+
module: So
|
|
4611
|
+
};
|
|
4612
|
+
case R.Ycbcr:
|
|
4613
|
+
return null;
|
|
4614
|
+
case R.Cielab:
|
|
4615
|
+
return {
|
|
4616
|
+
module: bo
|
|
4617
|
+
};
|
|
4618
|
+
default:
|
|
4619
|
+
throw new Error(`Unsupported PhotometricInterpretation ${r}`);
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
function Ko(e, t) {
|
|
4623
|
+
const { module: n, props: r } = e;
|
|
4624
|
+
if (!r)
|
|
4625
|
+
return { module: n };
|
|
4626
|
+
const o = {};
|
|
4627
|
+
for (const [i, s] of Object.entries(r)) {
|
|
4628
|
+
const a = typeof s == "function" ? s(t) : s;
|
|
4629
|
+
a !== void 0 && (o[i] = a);
|
|
4630
|
+
}
|
|
4631
|
+
return { module: n, props: o };
|
|
4632
|
+
}
|
|
4633
|
+
function _o(e, t) {
|
|
4634
|
+
const r = [
|
|
4635
|
+
...[...e.overviews].reverse(),
|
|
4636
|
+
e
|
|
4637
|
+
].map((o) => new on({
|
|
4638
|
+
affine: o.transform,
|
|
4639
|
+
arrayWidth: o.width,
|
|
4640
|
+
arrayHeight: o.height,
|
|
4641
|
+
tileWidth: o.tileWidth,
|
|
4642
|
+
tileHeight: o.tileHeight,
|
|
4643
|
+
mpu: t.mpu
|
|
4644
|
+
}));
|
|
4645
|
+
return new en({
|
|
4646
|
+
levels: r,
|
|
4647
|
+
projectTo3857: t.projectTo3857,
|
|
4648
|
+
projectFrom3857: t.projectFrom3857,
|
|
4649
|
+
projectTo4326: t.projectTo4326,
|
|
4650
|
+
projectFrom4326: t.projectFrom4326
|
|
4651
|
+
});
|
|
4652
|
+
}
|
|
4653
|
+
class Xo extends Be {
|
|
4654
|
+
static layerName = "COGLayer";
|
|
4655
|
+
// COGLayer's getTileData signature differs from the base class's, so
|
|
4656
|
+
// `DefaultProps<COGLayerProps>` is not assignable to
|
|
4657
|
+
// `DefaultProps<RasterTileLayerProps>`. Cast to the base static-side type
|
|
4658
|
+
// to keep inheritance happy. The only COG-specific default is
|
|
4659
|
+
// `epsgResolver`; all behavior still flows from the base class.
|
|
4660
|
+
static defaultProps = {
|
|
4661
|
+
...Be.defaultProps,
|
|
4662
|
+
epsgResolver: an
|
|
4663
|
+
};
|
|
4664
|
+
initializeState() {
|
|
4665
|
+
this.setState({});
|
|
4666
|
+
}
|
|
4667
|
+
updateState(t) {
|
|
4668
|
+
super.updateState(t);
|
|
4669
|
+
const { props: n, oldProps: r, changeFlags: o } = t;
|
|
4670
|
+
(!!o.dataChanged || n.geotiff !== r.geotiff) && (this.clearState(), this._parseGeoTIFF());
|
|
4671
|
+
}
|
|
4672
|
+
clearState() {
|
|
4673
|
+
this.setState({
|
|
4674
|
+
geotiff: void 0,
|
|
4675
|
+
tilesetDescriptor: void 0,
|
|
4676
|
+
defaultGetTileData: void 0,
|
|
4677
|
+
defaultRenderTile: void 0
|
|
4678
|
+
});
|
|
4679
|
+
}
|
|
4680
|
+
async _parseGeoTIFF() {
|
|
4681
|
+
const t = await go(this.props.geotiff), n = t.crs, r = typeof n == "number" ? await this.props.epsgResolver(n) : ot(n), o = Ae(r, "EPSG:4326"), i = (f, y) => o.forward([f, y], !1), s = (f, y) => o.inverse([f, y], !1), a = Ae(r, "EPSG:3857"), l = un((f, y) => a.forward([f, y], !1), i), c = (f, y) => a.inverse([f, y], !1), u = r.units;
|
|
4682
|
+
if (!u)
|
|
4683
|
+
throw new Error("Source projection is missing 'units' property, cannot compute meters per unit");
|
|
4684
|
+
const h = sn(u, {
|
|
4685
|
+
semiMajorAxis: r.datum?.a ?? r.a
|
|
4686
|
+
}), p = _o(t, {
|
|
4687
|
+
projectTo4326: i,
|
|
4688
|
+
projectFrom4326: s,
|
|
4689
|
+
projectTo3857: l,
|
|
4690
|
+
projectFrom3857: c,
|
|
4691
|
+
mpu: h
|
|
4692
|
+
});
|
|
4693
|
+
if (this.props.onGeoTIFFLoad) {
|
|
4694
|
+
const f = fo(t, o);
|
|
4695
|
+
this.props.onGeoTIFFLoad(t, {
|
|
4696
|
+
projection: r,
|
|
4697
|
+
geographicBounds: f
|
|
4698
|
+
});
|
|
4699
|
+
}
|
|
4700
|
+
let d, g;
|
|
4701
|
+
(!this.props.getTileData || !this.props.renderTile) && ({ getTileData: d, renderTile: g } = Uo(t, this.context.device)), this.setState({
|
|
4702
|
+
geotiff: t,
|
|
4703
|
+
tilesetDescriptor: p,
|
|
4704
|
+
defaultGetTileData: d,
|
|
4705
|
+
defaultRenderTile: g
|
|
4706
|
+
});
|
|
4707
|
+
}
|
|
4708
|
+
_tilesetDescriptor() {
|
|
4709
|
+
return this.state.tilesetDescriptor;
|
|
4710
|
+
}
|
|
4711
|
+
/**
|
|
4712
|
+
* Adapts the user-facing `(image, { x, y, ... }) => Promise<DataT>` signature
|
|
4713
|
+
* into RasterTileLayer's `(tile, { signal, device }) => Promise<DataT>`.
|
|
4714
|
+
*/
|
|
4715
|
+
_getTileDataCallback() {
|
|
4716
|
+
const t = this.state.geotiff;
|
|
4717
|
+
if (!t)
|
|
4718
|
+
return;
|
|
4719
|
+
const n = this.props.getTileData ?? this.state.defaultGetTileData;
|
|
4720
|
+
return n ? async (o, i) => {
|
|
4721
|
+
const { x: s, y: a, z: l } = o.index, c = l === t.overviews.length ? t : t.overviews[t.overviews.length - 1 - l];
|
|
4722
|
+
return n(c, {
|
|
4723
|
+
device: i.device,
|
|
4724
|
+
x: s,
|
|
4725
|
+
y: a,
|
|
4726
|
+
signal: i.signal,
|
|
4727
|
+
pool: this.props.pool ?? po()
|
|
4728
|
+
});
|
|
4729
|
+
} : void 0;
|
|
4730
|
+
}
|
|
4731
|
+
_renderTileCallback() {
|
|
4732
|
+
const t = this.props.renderTile ?? this.state.defaultRenderTile;
|
|
4733
|
+
if (t)
|
|
4734
|
+
return t;
|
|
4735
|
+
}
|
|
4736
|
+
}
|
|
4737
|
+
const Wo = "data:image/png;base64,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", $e = /* @__PURE__ */ new WeakMap();
|
|
4738
|
+
function Ho(e) {
|
|
4739
|
+
const t = $e.get(e);
|
|
4740
|
+
if (t) return t;
|
|
4741
|
+
const n = (async () => {
|
|
4742
|
+
const r = await (await fetch(Wo)).arrayBuffer();
|
|
4743
|
+
return jo(e, await xo(r));
|
|
4744
|
+
})();
|
|
4745
|
+
return $e.set(e, n), n;
|
|
4746
|
+
}
|
|
4747
|
+
const et = /* @__PURE__ */ new Set();
|
|
4748
|
+
function ko(e) {
|
|
4749
|
+
return e in he ? he[e] : (et.has(e) || (et.add(e), console.warn(`[onlymapjs] COGLayer: unknown colormap "${e}" — falling back to gray.`)), he.gray);
|
|
4750
|
+
}
|
|
4751
|
+
function Zo(e) {
|
|
4752
|
+
const t = e.layout === "band-separate" ? e.bands[0] : e.data;
|
|
4753
|
+
return t instanceof Float32Array ? t : new Float32Array(t);
|
|
4754
|
+
}
|
|
4755
|
+
function Vo(e) {
|
|
4756
|
+
const t = e.width * e.height, n = new Float32Array(t * 4);
|
|
4757
|
+
if (e.layout === "band-separate") {
|
|
4758
|
+
const [r, o, i] = [e.bands[0], e.bands[1], e.bands[2]];
|
|
4759
|
+
for (let s = 0; s < t; s++)
|
|
4760
|
+
n[s * 4] = r[s], n[s * 4 + 1] = o[s], n[s * 4 + 2] = i[s], n[s * 4 + 3] = 1;
|
|
4761
|
+
} else {
|
|
4762
|
+
const { data: r, count: o } = e;
|
|
4763
|
+
for (let i = 0; i < t; i++)
|
|
4764
|
+
n[i * 4] = r[i * o], n[i * 4 + 1] = r[i * o + 1], n[i * 4 + 2] = r[i * o + 2], n[i * 4 + 3] = 1;
|
|
4765
|
+
}
|
|
4766
|
+
return n;
|
|
4767
|
+
}
|
|
4768
|
+
const Yo = async (e, { device: t, x: n, y: r, signal: o, pool: i }) => {
|
|
4769
|
+
const s = () => {
|
|
4770
|
+
throw o?.reason ?? new DOMException("aborted", "AbortError");
|
|
4771
|
+
};
|
|
4772
|
+
o?.aborted && s();
|
|
4773
|
+
const a = await e.fetchTile(n, r, { boundless: !1, pool: i, signal: o });
|
|
4774
|
+
o?.aborted && s();
|
|
4775
|
+
const l = a.array, c = e.cachedTags.samplesPerPixel, u = { minFilter: "nearest", magFilter: "nearest" }, h = c === 1, p = h ? Zo(l) : Vo(l), d = t.createTexture({
|
|
4776
|
+
data: p,
|
|
4777
|
+
format: h ? "r32float" : "rgba32float",
|
|
4778
|
+
width: l.width,
|
|
4779
|
+
height: l.height,
|
|
4780
|
+
sampler: u
|
|
4781
|
+
});
|
|
4782
|
+
return {
|
|
4783
|
+
width: l.width,
|
|
4784
|
+
height: l.height,
|
|
4785
|
+
byteLength: p.byteLength,
|
|
4786
|
+
texture: d,
|
|
4787
|
+
colormapTexture: await Ho(t),
|
|
4788
|
+
bandCount: c,
|
|
4789
|
+
nodata: l.nodata
|
|
4790
|
+
};
|
|
4791
|
+
};
|
|
4792
|
+
function Jo(e, t) {
|
|
4793
|
+
const n = [
|
|
4794
|
+
// Per-tile textureName (not the layer-level `image:` shorthand — that
|
|
4795
|
+
// binds only the first tile's sampler in this setup).
|
|
4796
|
+
{ module: Se, props: { textureName: e.texture } }
|
|
4797
|
+
], r = t.nodataOverride ?? e.nodata;
|
|
4798
|
+
return r != null && Number.isFinite(r) && n.push({ module: Et, props: { value: r } }), n.push({
|
|
4799
|
+
module: Io,
|
|
4800
|
+
props: { rescaleMin: t.rescaleMin ?? 0, rescaleMax: t.rescaleMax ?? 255 }
|
|
4801
|
+
}), e.bandCount === 1 && n.push({
|
|
4802
|
+
module: At,
|
|
4803
|
+
props: { colormapTexture: e.colormapTexture, colormapIndex: ko(t.colormap ?? "gray") }
|
|
4804
|
+
}), { renderPipeline: n };
|
|
4805
|
+
}
|
|
4806
|
+
class qo extends Xo {
|
|
4807
|
+
static layerName = "OmCOGLayer";
|
|
4808
|
+
// Plain nulls (not `{type:"number", value:null}` specs): deck's typed
|
|
4809
|
+
// number props reject null defaults with a console warning per instance.
|
|
4810
|
+
static defaultProps = {
|
|
4811
|
+
rescaleMin: null,
|
|
4812
|
+
rescaleMax: null,
|
|
4813
|
+
colormap: null,
|
|
4814
|
+
nodataOverride: null
|
|
4815
|
+
};
|
|
4816
|
+
constructor(t) {
|
|
4817
|
+
const n = t;
|
|
4818
|
+
if (!(n.rescaleMin != null || n.rescaleMax != null || n.colormap != null && n.colormap !== "" || n.nodataOverride != null)) {
|
|
4819
|
+
super(t);
|
|
4820
|
+
return;
|
|
4821
|
+
}
|
|
4822
|
+
super(t, {
|
|
4823
|
+
getTileData: Yo,
|
|
4824
|
+
renderTile: (o) => o ? Jo(o, n) : null,
|
|
4825
|
+
// Free the per-tile texture on cache eviction; the sprite texture is
|
|
4826
|
+
// device-scoped (WeakMap above) and must NOT be destroyed here.
|
|
4827
|
+
onTileUnload: (o) => {
|
|
4828
|
+
const i = o.data;
|
|
4829
|
+
i && typeof i == "object" && "texture" in i && i.texture.destroy();
|
|
4830
|
+
}
|
|
4831
|
+
});
|
|
4832
|
+
}
|
|
4833
|
+
}
|
|
4834
|
+
const ei = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
4835
|
+
__proto__: null,
|
|
4836
|
+
OmCOGLayer: qo
|
|
4837
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
4838
|
+
export {
|
|
4839
|
+
P as C,
|
|
4840
|
+
D,
|
|
4841
|
+
ei as r
|
|
4842
|
+
};
|