@developmentseed/deck.gl-raster 0.1.0-beta.1 → 0.1.0-beta.3
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/dist/index.cjs +0 -725
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -141
- package/dist/index.d.ts +5 -142
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -722
- package/dist/index.js.map +1 -1
- package/dist/layer.d.ts +72 -0
- package/dist/layer.d.ts.map +1 -0
- package/dist/layer.js +88 -0
- package/dist/layer.js.map +1 -0
- package/dist/mesh.d.ts +1 -0
- package/dist/mesh.d.ts.map +1 -0
- package/dist/mesh.js +2 -0
- package/dist/mesh.js.map +1 -0
- package/dist/raster-debug-layer.d.ts +51 -0
- package/dist/raster-debug-layer.d.ts.map +1 -0
- package/dist/raster-debug-layer.js +102 -0
- package/dist/raster-debug-layer.js.map +1 -0
- package/dist/raster-layer.d.ts +63 -0
- package/dist/raster-layer.d.ts.map +1 -0
- package/dist/raster-layer.js +102 -0
- package/dist/raster-layer.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/layer.d.ts +1 -0
- package/dist/src/layer.d.ts.map +1 -0
- package/dist/src/layer.js +3 -0
- package/dist/src/layer.js.map +1 -0
- package/dist/src/mesh.d.ts +1 -0
- package/dist/src/mesh.d.ts.map +1 -0
- package/dist/src/mesh.js +2 -0
- package/dist/src/mesh.js.map +1 -0
- package/dist/tests/placeholder.test.d.ts +2 -0
- package/dist/tests/placeholder.test.d.ts.map +1 -0
- package/dist/tests/placeholder.test.js +7 -0
- package/dist/tests/placeholder.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +22 -26
- package/README.md +0 -80
package/dist/index.cjs
CHANGED
|
@@ -1,729 +1,4 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var proj4 = require('proj4');
|
|
4
|
-
|
|
5
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
-
|
|
7
|
-
var proj4__default = /*#__PURE__*/_interopDefault(proj4);
|
|
8
|
-
|
|
9
|
-
var __defProp = Object.defineProperty;
|
|
10
|
-
var __export = (target, all) => {
|
|
11
|
-
for (var name in all)
|
|
12
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
// src/reprojection/index.ts
|
|
16
|
-
var reprojection_exports = {};
|
|
17
|
-
__export(reprojection_exports, {
|
|
18
|
-
RasterReprojector: () => RasterReprojector,
|
|
19
|
-
affine: () => affine_exports,
|
|
20
|
-
extractGeotiffReprojectors: () => extractGeotiffReprojectors,
|
|
21
|
-
fromGeoTransform: () => fromGeoTransform
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// src/reprojection/delatin.ts
|
|
25
|
-
var SAMPLE_POINTS = [
|
|
26
|
-
[1 / 3, 1 / 3, 1 / 3],
|
|
27
|
-
// centroid
|
|
28
|
-
[0.5, 0.5, 0],
|
|
29
|
-
// edge 0–1
|
|
30
|
-
[0.5, 0, 0.5],
|
|
31
|
-
// edge 0–2
|
|
32
|
-
[0, 0.5, 0.5]
|
|
33
|
-
// edge 1–2
|
|
34
|
-
];
|
|
35
|
-
var RasterReprojector = class {
|
|
36
|
-
reprojectors;
|
|
37
|
-
width;
|
|
38
|
-
height;
|
|
39
|
-
/**
|
|
40
|
-
* UV vertex coordinates (x, y), i.e.
|
|
41
|
-
* [x0, y0, x1, y1, ...]
|
|
42
|
-
*
|
|
43
|
-
* These coordinates are floats that range from [0, 1] in both X and Y.
|
|
44
|
-
*/
|
|
45
|
-
uvs;
|
|
46
|
-
/**
|
|
47
|
-
* XY Positions in output CRS, computed via exact forward reprojection.
|
|
48
|
-
*/
|
|
49
|
-
exactOutputPositions;
|
|
50
|
-
/**
|
|
51
|
-
* triangle vertex indices
|
|
52
|
-
*/
|
|
53
|
-
triangles;
|
|
54
|
-
_halfedges;
|
|
55
|
-
/**
|
|
56
|
-
* The UV texture coordinates of candidates found from
|
|
57
|
-
* `findReprojectionCandidate`.
|
|
58
|
-
*
|
|
59
|
-
* Maybe in the future we'll want to store the barycentric coordinates instead
|
|
60
|
-
* of just the uv coordinates?
|
|
61
|
-
*/
|
|
62
|
-
_candidatesUV;
|
|
63
|
-
_queueIndices;
|
|
64
|
-
_queue;
|
|
65
|
-
_errors;
|
|
66
|
-
_pending;
|
|
67
|
-
_pendingLen;
|
|
68
|
-
constructor(reprojectors, width, height = width) {
|
|
69
|
-
this.reprojectors = reprojectors;
|
|
70
|
-
this.width = width;
|
|
71
|
-
this.height = height;
|
|
72
|
-
this.uvs = [];
|
|
73
|
-
this.exactOutputPositions = [];
|
|
74
|
-
this.triangles = [];
|
|
75
|
-
this._halfedges = [];
|
|
76
|
-
this._candidatesUV = [];
|
|
77
|
-
this._queueIndices = [];
|
|
78
|
-
this._queue = [];
|
|
79
|
-
this._errors = [];
|
|
80
|
-
this._pending = [];
|
|
81
|
-
this._pendingLen = 0;
|
|
82
|
-
const u1 = 1;
|
|
83
|
-
const v1 = 1;
|
|
84
|
-
const p0 = this._addPoint(0, 0);
|
|
85
|
-
const p1 = this._addPoint(u1, 0);
|
|
86
|
-
const p2 = this._addPoint(0, v1);
|
|
87
|
-
const p3 = this._addPoint(u1, v1);
|
|
88
|
-
const t0 = this._addTriangle(p3, p0, p2, -1, -1, -1);
|
|
89
|
-
this._addTriangle(p0, p3, p1, t0, -1, -1);
|
|
90
|
-
this._flush();
|
|
91
|
-
}
|
|
92
|
-
// refine the mesh until its maximum error gets below the given one
|
|
93
|
-
run(maxError = 1) {
|
|
94
|
-
while (this.getMaxError() > maxError) {
|
|
95
|
-
this.refine();
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// refine the mesh with a single point
|
|
99
|
-
refine() {
|
|
100
|
-
this._step();
|
|
101
|
-
this._flush();
|
|
102
|
-
}
|
|
103
|
-
// max error of the current mesh
|
|
104
|
-
getMaxError() {
|
|
105
|
-
return this._errors[0];
|
|
106
|
-
}
|
|
107
|
-
// rasterize and queue all triangles that got added or updated in _step
|
|
108
|
-
_flush() {
|
|
109
|
-
for (let i = 0; i < this._pendingLen; i++) {
|
|
110
|
-
const t = this._pending[i];
|
|
111
|
-
this._findReprojectionCandidate(t);
|
|
112
|
-
}
|
|
113
|
-
this._pendingLen = 0;
|
|
114
|
-
}
|
|
115
|
-
// Original, upstream implementation of FindCandidate:
|
|
116
|
-
// // rasterize a triangle, find its max error, and queue it for processing
|
|
117
|
-
// private _findCandidate(
|
|
118
|
-
// p0x: number,
|
|
119
|
-
// p0y: number,
|
|
120
|
-
// p1x: number,
|
|
121
|
-
// p1y: number,
|
|
122
|
-
// p2x: number,
|
|
123
|
-
// p2y: number,
|
|
124
|
-
// t: number,
|
|
125
|
-
// ) {
|
|
126
|
-
// // triangle bounding box
|
|
127
|
-
// const minX = Math.min(p0x, p1x, p2x);
|
|
128
|
-
// const minY = Math.min(p0y, p1y, p2y);
|
|
129
|
-
// const maxX = Math.max(p0x, p1x, p2x);
|
|
130
|
-
// const maxY = Math.max(p0y, p1y, p2y);
|
|
131
|
-
// // forward differencing variables
|
|
132
|
-
// let w00 = orient(p1x, p1y, p2x, p2y, minX, minY);
|
|
133
|
-
// let w01 = orient(p2x, p2y, p0x, p0y, minX, minY);
|
|
134
|
-
// let w02 = orient(p0x, p0y, p1x, p1y, minX, minY);
|
|
135
|
-
// const a01 = p1y - p0y;
|
|
136
|
-
// const b01 = p0x - p1x;
|
|
137
|
-
// const a12 = p2y - p1y;
|
|
138
|
-
// const b12 = p1x - p2x;
|
|
139
|
-
// const a20 = p0y - p2y;
|
|
140
|
-
// const b20 = p2x - p0x;
|
|
141
|
-
// // pre-multiplied z values at vertices
|
|
142
|
-
// const a = orient(p0x, p0y, p1x, p1y, p2x, p2y);
|
|
143
|
-
// const z0 = this.heightAt(p0x, p0y) / a;
|
|
144
|
-
// const z1 = this.heightAt(p1x, p1y) / a;
|
|
145
|
-
// const z2 = this.heightAt(p2x, p2y) / a;
|
|
146
|
-
// // iterate over pixels in bounding box
|
|
147
|
-
// let maxError = 0;
|
|
148
|
-
// let mx = 0;
|
|
149
|
-
// let my = 0;
|
|
150
|
-
// for (let y = minY; y <= maxY; y++) {
|
|
151
|
-
// // compute starting offset
|
|
152
|
-
// let dx = 0;
|
|
153
|
-
// if (w00 < 0 && a12 !== 0) {
|
|
154
|
-
// dx = Math.max(dx, Math.floor(-w00 / a12));
|
|
155
|
-
// }
|
|
156
|
-
// if (w01 < 0 && a20 !== 0) {
|
|
157
|
-
// dx = Math.max(dx, Math.floor(-w01 / a20));
|
|
158
|
-
// }
|
|
159
|
-
// if (w02 < 0 && a01 !== 0) {
|
|
160
|
-
// dx = Math.max(dx, Math.floor(-w02 / a01));
|
|
161
|
-
// }
|
|
162
|
-
// let w0 = w00 + a12 * dx;
|
|
163
|
-
// let w1 = w01 + a20 * dx;
|
|
164
|
-
// let w2 = w02 + a01 * dx;
|
|
165
|
-
// let wasInside = false;
|
|
166
|
-
// for (let x = minX + dx; x <= maxX; x++) {
|
|
167
|
-
// // check if inside triangle
|
|
168
|
-
// if (w0 >= 0 && w1 >= 0 && w2 >= 0) {
|
|
169
|
-
// wasInside = true;
|
|
170
|
-
// // compute z using barycentric coordinates
|
|
171
|
-
// const z = z0 * w0 + z1 * w1 + z2 * w2;
|
|
172
|
-
// const dz = Math.abs(z - this.heightAt(x, y));
|
|
173
|
-
// if (dz > maxError) {
|
|
174
|
-
// maxError = dz;
|
|
175
|
-
// mx = x;
|
|
176
|
-
// my = y;
|
|
177
|
-
// }
|
|
178
|
-
// } else if (wasInside) {
|
|
179
|
-
// break;
|
|
180
|
-
// }
|
|
181
|
-
// w0 += a12;
|
|
182
|
-
// w1 += a20;
|
|
183
|
-
// w2 += a01;
|
|
184
|
-
// }
|
|
185
|
-
// w00 += b12;
|
|
186
|
-
// w01 += b20;
|
|
187
|
-
// w02 += b01;
|
|
188
|
-
// }
|
|
189
|
-
// if (
|
|
190
|
-
// (mx === p0x && my === p0y) ||
|
|
191
|
-
// (mx === p1x && my === p1y) ||
|
|
192
|
-
// (mx === p2x && my === p2y)
|
|
193
|
-
// ) {
|
|
194
|
-
// maxError = 0;
|
|
195
|
-
// }
|
|
196
|
-
// // update triangle metadata
|
|
197
|
-
// this._candidatesUV[2 * t] = mx;
|
|
198
|
-
// this._candidatesUV[2 * t + 1] = my;
|
|
199
|
-
// // add triangle to priority queue
|
|
200
|
-
// this._queuePush(t, maxError);
|
|
201
|
-
// }
|
|
202
|
-
/**
|
|
203
|
-
* Conversion of upstream's `_findCandidate` for reprojection error handling.
|
|
204
|
-
*
|
|
205
|
-
* @param {number} t The index (into `this.triangles`) of the pending triangle to process.
|
|
206
|
-
*
|
|
207
|
-
* @return {void} Doesn't return; instead modifies internal state.
|
|
208
|
-
*/
|
|
209
|
-
_findReprojectionCandidate(t) {
|
|
210
|
-
const a2 = 2 * this.triangles[t * 3 + 0];
|
|
211
|
-
const b2 = 2 * this.triangles[t * 3 + 1];
|
|
212
|
-
const c = 2 * this.triangles[t * 3 + 2];
|
|
213
|
-
const p0u = this.uvs[a2];
|
|
214
|
-
const p0v = this.uvs[a2 + 1];
|
|
215
|
-
const p1u = this.uvs[b2];
|
|
216
|
-
const p1v = this.uvs[b2 + 1];
|
|
217
|
-
const p2u = this.uvs[c];
|
|
218
|
-
const p2v = this.uvs[c + 1];
|
|
219
|
-
const out0x = this.exactOutputPositions[a2];
|
|
220
|
-
const out0y = this.exactOutputPositions[a2 + 1];
|
|
221
|
-
const out1x = this.exactOutputPositions[b2];
|
|
222
|
-
const out1y = this.exactOutputPositions[b2 + 1];
|
|
223
|
-
const out2x = this.exactOutputPositions[c];
|
|
224
|
-
const out2y = this.exactOutputPositions[c + 1];
|
|
225
|
-
let maxError = 0;
|
|
226
|
-
let maxErrorU = 0;
|
|
227
|
-
let maxErrorV = 0;
|
|
228
|
-
for (const samplePoint of SAMPLE_POINTS) {
|
|
229
|
-
const uvSampleU = barycentricMix(
|
|
230
|
-
p0u,
|
|
231
|
-
p1u,
|
|
232
|
-
p2u,
|
|
233
|
-
samplePoint[0],
|
|
234
|
-
samplePoint[1],
|
|
235
|
-
samplePoint[2]
|
|
236
|
-
);
|
|
237
|
-
const uvSampleV = barycentricMix(
|
|
238
|
-
p0v,
|
|
239
|
-
p1v,
|
|
240
|
-
p2v,
|
|
241
|
-
samplePoint[0],
|
|
242
|
-
samplePoint[1],
|
|
243
|
-
samplePoint[2]
|
|
244
|
-
);
|
|
245
|
-
const outSampleX = barycentricMix(
|
|
246
|
-
out0x,
|
|
247
|
-
out1x,
|
|
248
|
-
out2x,
|
|
249
|
-
samplePoint[0],
|
|
250
|
-
samplePoint[1],
|
|
251
|
-
samplePoint[2]
|
|
252
|
-
);
|
|
253
|
-
const outSampleY = barycentricMix(
|
|
254
|
-
out0y,
|
|
255
|
-
out1y,
|
|
256
|
-
out2y,
|
|
257
|
-
samplePoint[0],
|
|
258
|
-
samplePoint[1],
|
|
259
|
-
samplePoint[2]
|
|
260
|
-
);
|
|
261
|
-
const pixelExactX = uvSampleU * (this.width - 1);
|
|
262
|
-
const pixelExactY = uvSampleV * (this.height - 1);
|
|
263
|
-
const inputCRSSampled = this.reprojectors.inverseReproject(
|
|
264
|
-
outSampleX,
|
|
265
|
-
outSampleY
|
|
266
|
-
);
|
|
267
|
-
const pixelSampled = this.reprojectors.inputCRSToPixel(
|
|
268
|
-
inputCRSSampled[0],
|
|
269
|
-
inputCRSSampled[1]
|
|
270
|
-
);
|
|
271
|
-
const dx = pixelExactX - pixelSampled[0];
|
|
272
|
-
const dy = pixelExactY - pixelSampled[1];
|
|
273
|
-
const err = Math.hypot(dx, dy);
|
|
274
|
-
if (err > maxError) {
|
|
275
|
-
maxError = err;
|
|
276
|
-
maxErrorU = uvSampleU;
|
|
277
|
-
maxErrorV = uvSampleV;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
if (maxErrorU === p0u && maxErrorV === p0v || maxErrorU === p1u && maxErrorV === p1v || maxErrorU === p2u && maxErrorV === p2v) {
|
|
281
|
-
maxError = 0;
|
|
282
|
-
}
|
|
283
|
-
this._candidatesUV[2 * t] = maxErrorU;
|
|
284
|
-
this._candidatesUV[2 * t + 1] = maxErrorV;
|
|
285
|
-
this._queuePush(t, maxError);
|
|
286
|
-
}
|
|
287
|
-
// process the next triangle in the queue, splitting it with a new point
|
|
288
|
-
_step() {
|
|
289
|
-
const t = this._queuePop();
|
|
290
|
-
const e0 = t * 3 + 0;
|
|
291
|
-
const e1 = t * 3 + 1;
|
|
292
|
-
const e2 = t * 3 + 2;
|
|
293
|
-
const p0 = this.triangles[e0];
|
|
294
|
-
const p1 = this.triangles[e1];
|
|
295
|
-
const p2 = this.triangles[e2];
|
|
296
|
-
const au = this.uvs[2 * p0];
|
|
297
|
-
const av = this.uvs[2 * p0 + 1];
|
|
298
|
-
const bu = this.uvs[2 * p1];
|
|
299
|
-
const bv = this.uvs[2 * p1 + 1];
|
|
300
|
-
const cu = this.uvs[2 * p2];
|
|
301
|
-
const cv = this.uvs[2 * p2 + 1];
|
|
302
|
-
const pu = this._candidatesUV[2 * t];
|
|
303
|
-
const pv = this._candidatesUV[2 * t + 1];
|
|
304
|
-
const pn = this._addPoint(pu, pv);
|
|
305
|
-
if (orient(au, av, bu, bv, pu, pv) === 0) {
|
|
306
|
-
this._handleCollinear(pn, e0);
|
|
307
|
-
} else if (orient(bu, bv, cu, cv, pu, pv) === 0) {
|
|
308
|
-
this._handleCollinear(pn, e1);
|
|
309
|
-
} else if (orient(cu, cv, au, av, pu, pv) === 0) {
|
|
310
|
-
this._handleCollinear(pn, e2);
|
|
311
|
-
} else {
|
|
312
|
-
const h0 = this._halfedges[e0];
|
|
313
|
-
const h1 = this._halfedges[e1];
|
|
314
|
-
const h2 = this._halfedges[e2];
|
|
315
|
-
const t0 = this._addTriangle(p0, p1, pn, h0, -1, -1, e0);
|
|
316
|
-
const t1 = this._addTriangle(p1, p2, pn, h1, -1, t0 + 1);
|
|
317
|
-
const t2 = this._addTriangle(p2, p0, pn, h2, t0 + 2, t1 + 1);
|
|
318
|
-
this._legalize(t0);
|
|
319
|
-
this._legalize(t1);
|
|
320
|
-
this._legalize(t2);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
// add coordinates for a new vertex
|
|
324
|
-
_addPoint(u, v) {
|
|
325
|
-
const i = this.uvs.length >> 1;
|
|
326
|
-
this.uvs.push(u, v);
|
|
327
|
-
const pixelX = u * (this.width - 1);
|
|
328
|
-
const pixelY = v * (this.height - 1);
|
|
329
|
-
const inputPosition = this.reprojectors.pixelToInputCRS(pixelX, pixelY);
|
|
330
|
-
const exactOutputPosition = this.reprojectors.forwardReproject(
|
|
331
|
-
inputPosition[0],
|
|
332
|
-
inputPosition[1]
|
|
333
|
-
);
|
|
334
|
-
this.exactOutputPositions.push(
|
|
335
|
-
exactOutputPosition[0],
|
|
336
|
-
exactOutputPosition[1]
|
|
337
|
-
);
|
|
338
|
-
return i;
|
|
339
|
-
}
|
|
340
|
-
// add or update a triangle in the mesh
|
|
341
|
-
_addTriangle(a2, b2, c, ab, bc, ca, e2 = this.triangles.length) {
|
|
342
|
-
const t = e2 / 3;
|
|
343
|
-
this.triangles[e2 + 0] = a2;
|
|
344
|
-
this.triangles[e2 + 1] = b2;
|
|
345
|
-
this.triangles[e2 + 2] = c;
|
|
346
|
-
this._halfedges[e2 + 0] = ab;
|
|
347
|
-
this._halfedges[e2 + 1] = bc;
|
|
348
|
-
this._halfedges[e2 + 2] = ca;
|
|
349
|
-
if (ab >= 0) {
|
|
350
|
-
this._halfedges[ab] = e2 + 0;
|
|
351
|
-
}
|
|
352
|
-
if (bc >= 0) {
|
|
353
|
-
this._halfedges[bc] = e2 + 1;
|
|
354
|
-
}
|
|
355
|
-
if (ca >= 0) {
|
|
356
|
-
this._halfedges[ca] = e2 + 2;
|
|
357
|
-
}
|
|
358
|
-
this._candidatesUV[2 * t + 0] = 0;
|
|
359
|
-
this._candidatesUV[2 * t + 1] = 0;
|
|
360
|
-
this._queueIndices[t] = -1;
|
|
361
|
-
this._pending[this._pendingLen++] = t;
|
|
362
|
-
return e2;
|
|
363
|
-
}
|
|
364
|
-
_legalize(a2) {
|
|
365
|
-
const b2 = this._halfedges[a2];
|
|
366
|
-
if (b2 < 0) {
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
const a0 = a2 - a2 % 3;
|
|
370
|
-
const b0 = b2 - b2 % 3;
|
|
371
|
-
const al = a0 + (a2 + 1) % 3;
|
|
372
|
-
const ar = a0 + (a2 + 2) % 3;
|
|
373
|
-
const bl = b0 + (b2 + 2) % 3;
|
|
374
|
-
const br = b0 + (b2 + 1) % 3;
|
|
375
|
-
const p0 = this.triangles[ar];
|
|
376
|
-
const pr = this.triangles[a2];
|
|
377
|
-
const pl = this.triangles[al];
|
|
378
|
-
const p1 = this.triangles[bl];
|
|
379
|
-
const uvs = this.uvs;
|
|
380
|
-
if (!inCircle(
|
|
381
|
-
uvs[2 * p0],
|
|
382
|
-
uvs[2 * p0 + 1],
|
|
383
|
-
uvs[2 * pr],
|
|
384
|
-
uvs[2 * pr + 1],
|
|
385
|
-
uvs[2 * pl],
|
|
386
|
-
uvs[2 * pl + 1],
|
|
387
|
-
uvs[2 * p1],
|
|
388
|
-
uvs[2 * p1 + 1]
|
|
389
|
-
)) {
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
const hal = this._halfedges[al];
|
|
393
|
-
const har = this._halfedges[ar];
|
|
394
|
-
const hbl = this._halfedges[bl];
|
|
395
|
-
const hbr = this._halfedges[br];
|
|
396
|
-
this._queueRemove(a0 / 3);
|
|
397
|
-
this._queueRemove(b0 / 3);
|
|
398
|
-
const t0 = this._addTriangle(p0, p1, pl, -1, hbl, hal, a0);
|
|
399
|
-
const t1 = this._addTriangle(p1, p0, pr, t0, har, hbr, b0);
|
|
400
|
-
this._legalize(t0 + 1);
|
|
401
|
-
this._legalize(t1 + 2);
|
|
402
|
-
}
|
|
403
|
-
// handle a case where new vertex is on the edge of a triangle
|
|
404
|
-
_handleCollinear(pn, a2) {
|
|
405
|
-
const a0 = a2 - a2 % 3;
|
|
406
|
-
const al = a0 + (a2 + 1) % 3;
|
|
407
|
-
const ar = a0 + (a2 + 2) % 3;
|
|
408
|
-
const p0 = this.triangles[ar];
|
|
409
|
-
const pr = this.triangles[a2];
|
|
410
|
-
const pl = this.triangles[al];
|
|
411
|
-
const hal = this._halfedges[al];
|
|
412
|
-
const har = this._halfedges[ar];
|
|
413
|
-
const b2 = this._halfedges[a2];
|
|
414
|
-
if (b2 < 0) {
|
|
415
|
-
const t02 = this._addTriangle(pn, p0, pr, -1, har, -1, a0);
|
|
416
|
-
const t12 = this._addTriangle(p0, pn, pl, t02, -1, hal);
|
|
417
|
-
this._legalize(t02 + 1);
|
|
418
|
-
this._legalize(t12 + 2);
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
const b0 = b2 - b2 % 3;
|
|
422
|
-
const bl = b0 + (b2 + 2) % 3;
|
|
423
|
-
const br = b0 + (b2 + 1) % 3;
|
|
424
|
-
const p1 = this.triangles[bl];
|
|
425
|
-
const hbl = this._halfedges[bl];
|
|
426
|
-
const hbr = this._halfedges[br];
|
|
427
|
-
this._queueRemove(b0 / 3);
|
|
428
|
-
const t0 = this._addTriangle(p0, pr, pn, har, -1, -1, a0);
|
|
429
|
-
const t1 = this._addTriangle(pr, p1, pn, hbr, -1, t0 + 1, b0);
|
|
430
|
-
const t2 = this._addTriangle(p1, pl, pn, hbl, -1, t1 + 1);
|
|
431
|
-
const t3 = this._addTriangle(pl, p0, pn, hal, t0 + 2, t2 + 1);
|
|
432
|
-
this._legalize(t0);
|
|
433
|
-
this._legalize(t1);
|
|
434
|
-
this._legalize(t2);
|
|
435
|
-
this._legalize(t3);
|
|
436
|
-
}
|
|
437
|
-
// priority queue methods
|
|
438
|
-
_queuePush(t, error) {
|
|
439
|
-
const i = this._queue.length;
|
|
440
|
-
this._queueIndices[t] = i;
|
|
441
|
-
this._queue.push(t);
|
|
442
|
-
this._errors.push(error);
|
|
443
|
-
this._queueUp(i);
|
|
444
|
-
}
|
|
445
|
-
_queuePop() {
|
|
446
|
-
const n = this._queue.length - 1;
|
|
447
|
-
this._queueSwap(0, n);
|
|
448
|
-
this._queueDown(0, n);
|
|
449
|
-
return this._queuePopBack();
|
|
450
|
-
}
|
|
451
|
-
_queuePopBack() {
|
|
452
|
-
const t = this._queue.pop();
|
|
453
|
-
this._errors.pop();
|
|
454
|
-
this._queueIndices[t] = -1;
|
|
455
|
-
return t;
|
|
456
|
-
}
|
|
457
|
-
_queueRemove(t) {
|
|
458
|
-
const i = this._queueIndices[t];
|
|
459
|
-
if (i < 0) {
|
|
460
|
-
const it = this._pending.indexOf(t);
|
|
461
|
-
if (it !== -1) {
|
|
462
|
-
this._pending[it] = this._pending[--this._pendingLen];
|
|
463
|
-
} else {
|
|
464
|
-
throw new Error("Broken triangulation (something went wrong).");
|
|
465
|
-
}
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
const n = this._queue.length - 1;
|
|
469
|
-
if (n !== i) {
|
|
470
|
-
this._queueSwap(i, n);
|
|
471
|
-
if (!this._queueDown(i, n)) {
|
|
472
|
-
this._queueUp(i);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
this._queuePopBack();
|
|
476
|
-
}
|
|
477
|
-
_queueLess(i, j) {
|
|
478
|
-
return this._errors[i] > this._errors[j];
|
|
479
|
-
}
|
|
480
|
-
_queueSwap(i, j) {
|
|
481
|
-
const pi = this._queue[i];
|
|
482
|
-
const pj = this._queue[j];
|
|
483
|
-
this._queue[i] = pj;
|
|
484
|
-
this._queue[j] = pi;
|
|
485
|
-
this._queueIndices[pi] = j;
|
|
486
|
-
this._queueIndices[pj] = i;
|
|
487
|
-
const e2 = this._errors[i];
|
|
488
|
-
this._errors[i] = this._errors[j];
|
|
489
|
-
this._errors[j] = e2;
|
|
490
|
-
}
|
|
491
|
-
_queueUp(j0) {
|
|
492
|
-
let j = j0;
|
|
493
|
-
while (true) {
|
|
494
|
-
const i = j - 1 >> 1;
|
|
495
|
-
if (i === j || !this._queueLess(j, i)) {
|
|
496
|
-
break;
|
|
497
|
-
}
|
|
498
|
-
this._queueSwap(i, j);
|
|
499
|
-
j = i;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
_queueDown(i0, n) {
|
|
503
|
-
let i = i0;
|
|
504
|
-
while (true) {
|
|
505
|
-
const j1 = 2 * i + 1;
|
|
506
|
-
if (j1 >= n || j1 < 0) {
|
|
507
|
-
break;
|
|
508
|
-
}
|
|
509
|
-
const j2 = j1 + 1;
|
|
510
|
-
let j = j1;
|
|
511
|
-
if (j2 < n && this._queueLess(j2, j1)) {
|
|
512
|
-
j = j2;
|
|
513
|
-
}
|
|
514
|
-
if (!this._queueLess(j, i)) {
|
|
515
|
-
break;
|
|
516
|
-
}
|
|
517
|
-
this._queueSwap(i, j);
|
|
518
|
-
i = j;
|
|
519
|
-
}
|
|
520
|
-
return i > i0;
|
|
521
|
-
}
|
|
522
|
-
};
|
|
523
|
-
function orient(ax, ay, bx, by, cx, cy) {
|
|
524
|
-
return (bx - cx) * (ay - cy) - (by - cy) * (ax - cx);
|
|
525
|
-
}
|
|
526
|
-
function inCircle(ax, ay, bx, by, cx, cy, px, py) {
|
|
527
|
-
const dx = ax - px;
|
|
528
|
-
const dy = ay - py;
|
|
529
|
-
const ex = bx - px;
|
|
530
|
-
const ey = by - py;
|
|
531
|
-
const fx = cx - px;
|
|
532
|
-
const fy = cy - py;
|
|
533
|
-
const ap = dx * dx + dy * dy;
|
|
534
|
-
const bp = ex * ex + ey * ey;
|
|
535
|
-
const cp = fx * fx + fy * fy;
|
|
536
|
-
return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0;
|
|
537
|
-
}
|
|
538
|
-
function barycentricMix(a2, b2, c, t0, t1, t2) {
|
|
539
|
-
return t0 * a2 + t1 * b2 + t2 * c;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// src/reprojection/affine.ts
|
|
543
|
-
var affine_exports = {};
|
|
544
|
-
__export(affine_exports, {
|
|
545
|
-
applyAffine: () => applyAffine,
|
|
546
|
-
invertGeoTransform: () => invertGeoTransform
|
|
547
|
-
});
|
|
548
|
-
function invertGeoTransform(gt) {
|
|
549
|
-
if (isDegenerate(gt)) {
|
|
550
|
-
throw new Error("Cannot invert degenerate transform");
|
|
551
|
-
}
|
|
552
|
-
const idet = 1 / determinant(gt);
|
|
553
|
-
const [sa, sb, sc, sd, se, sf] = gt;
|
|
554
|
-
const ra = se * idet;
|
|
555
|
-
const rb = -sb * idet;
|
|
556
|
-
const rd = -sd * idet;
|
|
557
|
-
const re = sa * idet;
|
|
558
|
-
return [
|
|
559
|
-
ra,
|
|
560
|
-
rb,
|
|
561
|
-
-sc * ra - sf * rb,
|
|
562
|
-
rd,
|
|
563
|
-
re,
|
|
564
|
-
-sc * rd - sf * re
|
|
565
|
-
];
|
|
566
|
-
}
|
|
567
|
-
function isDegenerate(gt) {
|
|
568
|
-
return determinant(gt) === 0;
|
|
569
|
-
}
|
|
570
|
-
function determinant(gt) {
|
|
571
|
-
return a(gt) * e(gt) - b(gt) * d(gt);
|
|
572
|
-
}
|
|
573
|
-
function a(gt) {
|
|
574
|
-
return gt[0];
|
|
575
|
-
}
|
|
576
|
-
function b(gt) {
|
|
577
|
-
return gt[1];
|
|
578
|
-
}
|
|
579
|
-
function d(gt) {
|
|
580
|
-
return gt[3];
|
|
581
|
-
}
|
|
582
|
-
function e(gt) {
|
|
583
|
-
return gt[4];
|
|
584
|
-
}
|
|
585
|
-
function applyAffine(x, y, gt) {
|
|
586
|
-
const [a2, b2, c, d2, e2, f] = gt;
|
|
587
|
-
return [a2 * x + b2 * y + c, d2 * x + e2 * y + f];
|
|
588
|
-
}
|
|
589
|
-
var OGC_84 = {
|
|
590
|
-
$schema: "https://proj.org/schemas/v0.7/projjson.schema.json",
|
|
591
|
-
type: "GeographicCRS",
|
|
592
|
-
name: "WGS 84 (CRS84)",
|
|
593
|
-
datum_ensemble: {
|
|
594
|
-
name: "World Geodetic System 1984 ensemble",
|
|
595
|
-
members: [
|
|
596
|
-
{
|
|
597
|
-
name: "World Geodetic System 1984 (Transit)",
|
|
598
|
-
id: { authority: "EPSG", code: 1166 }
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
name: "World Geodetic System 1984 (G730)",
|
|
602
|
-
id: { authority: "EPSG", code: 1152 }
|
|
603
|
-
},
|
|
604
|
-
{
|
|
605
|
-
name: "World Geodetic System 1984 (G873)",
|
|
606
|
-
id: { authority: "EPSG", code: 1153 }
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
name: "World Geodetic System 1984 (G1150)",
|
|
610
|
-
id: { authority: "EPSG", code: 1154 }
|
|
611
|
-
},
|
|
612
|
-
{
|
|
613
|
-
name: "World Geodetic System 1984 (G1674)",
|
|
614
|
-
id: { authority: "EPSG", code: 1155 }
|
|
615
|
-
},
|
|
616
|
-
{
|
|
617
|
-
name: "World Geodetic System 1984 (G1762)",
|
|
618
|
-
id: { authority: "EPSG", code: 1156 }
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
name: "World Geodetic System 1984 (G2139)",
|
|
622
|
-
id: { authority: "EPSG", code: 1309 }
|
|
623
|
-
}
|
|
624
|
-
],
|
|
625
|
-
ellipsoid: {
|
|
626
|
-
name: "WGS 84",
|
|
627
|
-
semi_major_axis: 6378137,
|
|
628
|
-
inverse_flattening: 298.257223563
|
|
629
|
-
},
|
|
630
|
-
accuracy: "2.0",
|
|
631
|
-
id: { authority: "EPSG", code: 6326 }
|
|
632
|
-
},
|
|
633
|
-
coordinate_system: {
|
|
634
|
-
subtype: "ellipsoidal",
|
|
635
|
-
axis: [
|
|
636
|
-
{
|
|
637
|
-
name: "Geodetic longitude",
|
|
638
|
-
abbreviation: "Lon",
|
|
639
|
-
direction: "east",
|
|
640
|
-
unit: "degree"
|
|
641
|
-
},
|
|
642
|
-
{
|
|
643
|
-
name: "Geodetic latitude",
|
|
644
|
-
abbreviation: "Lat",
|
|
645
|
-
direction: "north",
|
|
646
|
-
unit: "degree"
|
|
647
|
-
}
|
|
648
|
-
]
|
|
649
|
-
},
|
|
650
|
-
scope: "Not known.",
|
|
651
|
-
area: "World.",
|
|
652
|
-
bbox: {
|
|
653
|
-
south_latitude: -90,
|
|
654
|
-
west_longitude: -180,
|
|
655
|
-
north_latitude: 90,
|
|
656
|
-
east_longitude: 180
|
|
657
|
-
},
|
|
658
|
-
// @ts-expect-error - proj4 types are incomplete
|
|
659
|
-
id: { authority: "OGC", code: "CRS84" }
|
|
660
|
-
};
|
|
661
|
-
async function extractGeotiffReprojectors(tiff, outputCrs = OGC_84) {
|
|
662
|
-
const image = await tiff.getImage();
|
|
663
|
-
const geoKeys = image.getGeoKeys();
|
|
664
|
-
const projectionCode = geoKeys.ProjectedCSTypeGeoKey || geoKeys.GeographicTypeGeoKey || null;
|
|
665
|
-
const baseGeotransform = extractGeotransform(image);
|
|
666
|
-
const sourceProjection = await getProjjson(projectionCode);
|
|
667
|
-
if (sourceProjection === null) {
|
|
668
|
-
throw new Error(
|
|
669
|
-
"Could not determine source projection from GeoTIFF geo keys"
|
|
670
|
-
);
|
|
671
|
-
}
|
|
672
|
-
const converter = proj4__default.default(sourceProjection, outputCrs);
|
|
673
|
-
const { pixelToInputCRS, inputCRSToPixel } = fromGeoTransform(baseGeotransform);
|
|
674
|
-
return {
|
|
675
|
-
pixelToInputCRS,
|
|
676
|
-
inputCRSToPixel,
|
|
677
|
-
forwardReproject: (x, y) => converter.forward([x, y], false),
|
|
678
|
-
inverseReproject: (x, y) => converter.inverse([x, y], false)
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
|
-
function fromGeoTransform(geotransform) {
|
|
682
|
-
const inverseGeotransform = invertGeoTransform(geotransform);
|
|
683
|
-
return {
|
|
684
|
-
pixelToInputCRS: (x, y) => applyAffine(x, y, geotransform),
|
|
685
|
-
inputCRSToPixel: (x, y) => applyAffine(x, y, inverseGeotransform)
|
|
686
|
-
};
|
|
687
|
-
}
|
|
688
|
-
async function getProjjson(projectionCode) {
|
|
689
|
-
if (projectionCode === null) {
|
|
690
|
-
return null;
|
|
691
|
-
}
|
|
692
|
-
const url = `https://epsg.io/${projectionCode}.json`;
|
|
693
|
-
const response = await fetch(url);
|
|
694
|
-
if (!response.ok) {
|
|
695
|
-
throw new Error(`Failed to fetch projection data from ${url}`);
|
|
696
|
-
}
|
|
697
|
-
const data = await response.json();
|
|
698
|
-
return data;
|
|
699
|
-
}
|
|
700
|
-
function extractGeotransform(image) {
|
|
701
|
-
const origin = image.getOrigin();
|
|
702
|
-
const resolution = image.getResolution();
|
|
703
|
-
const fileDirectory = image.getFileDirectory();
|
|
704
|
-
const modelTransformation = fileDirectory.ModelTransformation;
|
|
705
|
-
let b2 = 0;
|
|
706
|
-
let d2 = 0;
|
|
707
|
-
if (modelTransformation && modelTransformation.length >= 16) {
|
|
708
|
-
b2 = modelTransformation[1];
|
|
709
|
-
d2 = modelTransformation[4];
|
|
710
|
-
}
|
|
711
|
-
return [
|
|
712
|
-
resolution[0],
|
|
713
|
-
// a: pixel width
|
|
714
|
-
b2,
|
|
715
|
-
// b: row rotation
|
|
716
|
-
origin[0],
|
|
717
|
-
// c: x origin
|
|
718
|
-
d2,
|
|
719
|
-
// d: column rotation
|
|
720
|
-
resolution[1],
|
|
721
|
-
// e: pixel height (often negative)
|
|
722
|
-
origin[1]
|
|
723
|
-
// f: y origin
|
|
724
|
-
];
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
exports.reprojection = reprojection_exports;
|
|
728
3
|
//# sourceMappingURL=index.cjs.map
|
|
729
4
|
//# sourceMappingURL=index.cjs.map
|