@naivemap/mapbox-gl-image-layer 0.4.2 → 0.6.0-beta.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 +25 -4
- package/dist/es/ImageLayer.js +232 -0
- package/dist/es/arrugator/Arrugator.js +270 -0
- package/dist/es/{utils/arrugator.js → arrugator/index.js} +43 -39
- package/dist/es/index.js +2 -132
- package/dist/es/shaders/image.fragment.glsl.js +1 -0
- package/dist/es/shaders/image.vertex.glsl.js +1 -0
- package/dist/es/shaders/mask.fragment.glsl.js +1 -0
- package/dist/es/shaders/mask.vertex.glsl.js +1 -0
- package/dist/js/ImageLayer.d.ts +62 -0
- package/dist/js/ImageLayer.js +270 -0
- package/dist/js/arrugator/Arrugator.d.ts +18 -0
- package/dist/js/arrugator/Arrugator.js +275 -0
- package/dist/js/arrugator/index.d.ts +7 -0
- package/dist/js/{utils/arrugator.js → arrugator/index.js} +49 -46
- package/dist/js/index.d.ts +4 -45
- package/dist/js/index.js +7 -134
- package/dist/js/shaders/image.fragment.glsl.d.ts +2 -0
- package/dist/js/shaders/image.fragment.glsl.js +3 -0
- package/dist/js/shaders/image.vertex.glsl.d.ts +2 -0
- package/dist/js/shaders/image.vertex.glsl.js +3 -0
- package/dist/js/shaders/mask.fragment.glsl.d.ts +2 -0
- package/dist/js/shaders/mask.fragment.glsl.js +3 -0
- package/dist/js/shaders/mask.vertex.glsl.d.ts +2 -0
- package/dist/js/shaders/mask.vertex.glsl.js +3 -0
- package/package.json +9 -6
- package/LICENSE +0 -21
- package/dist/es/utils/image.js +0 -19
- package/dist/es/utils/webgl.js +0 -64
- package/dist/js/utils/arrugator.d.ts +0 -7
- package/dist/js/utils/image.d.ts +0 -7
- package/dist/js/utils/image.js +0 -23
- package/dist/js/utils/webgl.d.ts +0 -8
- package/dist/js/utils/webgl.js +0 -68
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
/* eslint-disable guard-for-in */
|
|
7
|
+
// @ts-nocheck
|
|
8
|
+
var tinyqueue_1 = __importDefault(require("tinyqueue"));
|
|
9
|
+
var Arrugator = /** @class */ (function () {
|
|
10
|
+
function Arrugator(projector, verts, uv, trigs) {
|
|
11
|
+
this._stepsWithSameEpsilon = 0;
|
|
12
|
+
// The projector function. Must be able to take
|
|
13
|
+
// an array of two numbers [x,y] and return an array of
|
|
14
|
+
// two numbers.
|
|
15
|
+
// The typical use case is a proj4(from,to).forward function.
|
|
16
|
+
this._projector = projector;
|
|
17
|
+
// A two-dimensional array of vertex coordinates. Each vertex is a
|
|
18
|
+
// two-element [x,y] array.
|
|
19
|
+
this._verts = verts;
|
|
20
|
+
// A two-dimensional array of UV-map coordinates. These are intended to
|
|
21
|
+
// represent the [0,0]-[1-1] coordinate space of WebGL textures. Each
|
|
22
|
+
// n-th element is the UV coordinates of the n-th vertex. These shall
|
|
23
|
+
// be linearly interpolated when splitting segments.
|
|
24
|
+
this._uv = uv;
|
|
25
|
+
// A two-dimensional array of vertex coordinates, projected. Each
|
|
26
|
+
// vertex is a two-element [x,y] array.
|
|
27
|
+
this._projVerts = verts.map(projector);
|
|
28
|
+
// A two-dimensional array of triangle vertex IDs. Each triangle is a
|
|
29
|
+
// three-element [v1,v2,v3] array.
|
|
30
|
+
// The mesh is **expected** to be compact, planar, non-overlapping.
|
|
31
|
+
this._trigs = trigs;
|
|
32
|
+
// A map of segments to vertices. Key is the segment index (generated inside
|
|
33
|
+
// arrugator), value is an array of two vertex indices.
|
|
34
|
+
this._segs = [];
|
|
35
|
+
this._segCount = 0;
|
|
36
|
+
// A map of segments to triangles. Key is the segment index (generated inside
|
|
37
|
+
// arrugator), value is an array of triangle indices (all segments should
|
|
38
|
+
// have either 1 or 2 triangles associated)
|
|
39
|
+
this._segTrigs = [];
|
|
40
|
+
// A priority queue of segments, ordered by their epsilons, in descending order.
|
|
41
|
+
this._queue = new tinyqueue_1.default([], function (a, b) {
|
|
42
|
+
return b.epsilon - a.epsilon;
|
|
43
|
+
});
|
|
44
|
+
// A map of vertex indices to segment indices.
|
|
45
|
+
this._vertToSeg = new Array(verts.length);
|
|
46
|
+
for (var i in this._verts) {
|
|
47
|
+
this._vertToSeg[i] = [];
|
|
48
|
+
}
|
|
49
|
+
/// NOTE: Not using .fill([]), because that would use a reference to the *same*
|
|
50
|
+
/// empty array for every element.
|
|
51
|
+
for (var t in this._trigs) {
|
|
52
|
+
var trig = this._trigs[t];
|
|
53
|
+
var v0 = trig[0];
|
|
54
|
+
var v1 = trig[1];
|
|
55
|
+
var v2 = trig[2];
|
|
56
|
+
this._segment(v0, v1, t);
|
|
57
|
+
this._segment(v1, v2, t);
|
|
58
|
+
this._segment(v2, v0, t);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Returns the segment index linking the two given vertex indices;
|
|
62
|
+
// Must be passed a triangle index to use as context.
|
|
63
|
+
// Might create a new segment index (as well as segment data structure and
|
|
64
|
+
// entry in the priority queue).
|
|
65
|
+
Arrugator.prototype._segment = function (v1, v2, t, maxEpsilon) {
|
|
66
|
+
if (maxEpsilon === void 0) { maxEpsilon = Infinity; }
|
|
67
|
+
if (this._vertToSeg[v1] && this._vertToSeg[v1][v2] !== undefined) {
|
|
68
|
+
var found = this._vertToSeg[v1][v2];
|
|
69
|
+
if (!this._segTrigs[found].includes(t)) {
|
|
70
|
+
this._segTrigs[found].push(t);
|
|
71
|
+
}
|
|
72
|
+
return found;
|
|
73
|
+
}
|
|
74
|
+
var segIdx = this._segCount++;
|
|
75
|
+
this._segs[segIdx] = [v1, v2];
|
|
76
|
+
this._vertToSeg[v1][v2] = segIdx;
|
|
77
|
+
this._vertToSeg[v2][v1] = segIdx;
|
|
78
|
+
this._segTrigs[segIdx] = [t];
|
|
79
|
+
// Calculate segment epsilon
|
|
80
|
+
// The "epsilon" of a segment is the square of the midpoint projection distance:
|
|
81
|
+
// i.e. the square of the distance between:
|
|
82
|
+
// - the projected midpoint of the two vertices, and
|
|
83
|
+
// - the midpoint of the two projected vertices,
|
|
84
|
+
// the distance function being euclidean distance in the "destination"
|
|
85
|
+
// projection, squared.
|
|
86
|
+
var midpoint = [
|
|
87
|
+
(this._verts[v1][0] + this._verts[v2][0]) / 2,
|
|
88
|
+
(this._verts[v1][1] + this._verts[v2][1]) / 2,
|
|
89
|
+
];
|
|
90
|
+
var projectedMid = this._projector(midpoint);
|
|
91
|
+
var midProjected = [
|
|
92
|
+
(this._projVerts[v1][0] + this._projVerts[v2][0]) / 2,
|
|
93
|
+
(this._projVerts[v1][1] + this._projVerts[v2][1]) / 2,
|
|
94
|
+
];
|
|
95
|
+
var epsilon = Math.pow((projectedMid[0] - midProjected[0]), 2) + Math.pow((projectedMid[1] - midProjected[1]), 2);
|
|
96
|
+
if (Number.isFinite(epsilon) && epsilon < maxEpsilon) {
|
|
97
|
+
this._queue.push({
|
|
98
|
+
v1: v1,
|
|
99
|
+
v2: v2,
|
|
100
|
+
epsilon: epsilon,
|
|
101
|
+
midpoint: midpoint,
|
|
102
|
+
projectedMid: projectedMid,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
return segIdx;
|
|
106
|
+
};
|
|
107
|
+
// Outputs shallow copies of some data structures at the current step.
|
|
108
|
+
Arrugator.prototype.output = function () {
|
|
109
|
+
// Most data structs are 2-dimensional arrays, and doing a shallow copy
|
|
110
|
+
// of the first level *should* just work.
|
|
111
|
+
return {
|
|
112
|
+
unprojected: Array.from(this._verts),
|
|
113
|
+
projected: Array.from(this._projVerts),
|
|
114
|
+
uv: Array.from(this._uv),
|
|
115
|
+
trigs: Array.from(this._trigs),
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
// Subdivides the mesh until the maximum segment epsilon is below the
|
|
119
|
+
// given threshold.
|
|
120
|
+
// The `targetEpsilon` parameter must be in the same units as the
|
|
121
|
+
// internal epsilons: units of the projected CRS, **squared**.
|
|
122
|
+
Arrugator.prototype.lowerEpsilon = function (targetEpsilon) {
|
|
123
|
+
var currentEpsilon = this._queue.peek().epsilon;
|
|
124
|
+
var lastEpsilon = currentEpsilon;
|
|
125
|
+
while (currentEpsilon >= targetEpsilon) {
|
|
126
|
+
this.step();
|
|
127
|
+
currentEpsilon = this._queue.peek().epsilon;
|
|
128
|
+
if (currentEpsilon === lastEpsilon) {
|
|
129
|
+
this._stepsWithSameEpsilon++;
|
|
130
|
+
if (this._stepsWithSameEpsilon < 500) {
|
|
131
|
+
console.warn('Arrugator stopped due to epsilon stall. Raster may need hints for proper arrugation.');
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
this._stepsWithSameEpsilon = 0;
|
|
137
|
+
lastEpsilon = currentEpsilon;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
Object.defineProperty(Arrugator.prototype, "epsilon", {
|
|
142
|
+
get: function () {
|
|
143
|
+
return this._queue.peek().epsilon;
|
|
144
|
+
},
|
|
145
|
+
set: function (ep) {
|
|
146
|
+
return this.lowerEpsilon(ep);
|
|
147
|
+
},
|
|
148
|
+
enumerable: false,
|
|
149
|
+
configurable: true
|
|
150
|
+
});
|
|
151
|
+
// Triggers subdivision of the segment with the largest epsilon.
|
|
152
|
+
Arrugator.prototype.step = function () {
|
|
153
|
+
var seg = this._queue.pop();
|
|
154
|
+
return this._splitSegment(seg, seg.epsilon);
|
|
155
|
+
};
|
|
156
|
+
// Triggers *one* subdivision of *all* segments in the queue.
|
|
157
|
+
// Can be useful to run this prior to stepping, in order to overcome
|
|
158
|
+
// artefacts
|
|
159
|
+
Arrugator.prototype.force = function () {
|
|
160
|
+
var _this = this;
|
|
161
|
+
var segments = this._queue.data;
|
|
162
|
+
this._queue.data = []; // Empties the queue
|
|
163
|
+
this._queue.length = 0;
|
|
164
|
+
segments.forEach(function (seg) { return _this._splitSegment(seg, Infinity); });
|
|
165
|
+
};
|
|
166
|
+
// Splits the given segment.
|
|
167
|
+
// This deletes the segment, spawns a new vertex at the midpoint, and
|
|
168
|
+
// for each triangle the segment was originally a part of (either 1 or 2),
|
|
169
|
+
// the triangle is divided into two.
|
|
170
|
+
Arrugator.prototype._splitSegment = function (seg, maxEpsilon) {
|
|
171
|
+
// Which are the two vertices affected by the popped segment?
|
|
172
|
+
var v1 = seg.v1;
|
|
173
|
+
var v2 = seg.v2;
|
|
174
|
+
var s = this._vertToSeg[v1] && this._vertToSeg[v1][v2];
|
|
175
|
+
// Which triangle(s) are affected by the popped segment?
|
|
176
|
+
var trigs = this._segTrigs[s];
|
|
177
|
+
// Sanity check
|
|
178
|
+
if (trigs.length >= 3) {
|
|
179
|
+
throw new Error('Somehow a segment is shared by three triangles');
|
|
180
|
+
}
|
|
181
|
+
// Clean up refs
|
|
182
|
+
delete this._segTrigs[s];
|
|
183
|
+
delete this._segs[s];
|
|
184
|
+
delete this._vertToSeg[v1][v2];
|
|
185
|
+
delete this._vertToSeg[v2][v1];
|
|
186
|
+
// What is the vertex ID of the new midpoint vertex?
|
|
187
|
+
var vm = this._verts.length;
|
|
188
|
+
this._projVerts[vm] = seg.projectedMid;
|
|
189
|
+
this._verts[vm] = seg.midpoint;
|
|
190
|
+
this._vertToSeg[vm] = [];
|
|
191
|
+
this._uv[vm] = [
|
|
192
|
+
(this._uv[v1][0] + this._uv[v2][0]) / 2,
|
|
193
|
+
(this._uv[v1][1] + this._uv[v2][1]) / 2,
|
|
194
|
+
];
|
|
195
|
+
for (var _i = 0, trigs_1 = trigs; _i < trigs_1.length; _i++) {
|
|
196
|
+
var t = trigs_1[_i];
|
|
197
|
+
this._splitTriangle(v1, v2, vm, t, maxEpsilon);
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
// Split a triangle in two.
|
|
201
|
+
// Must be given vertex indices of the segment being splitted, the index of the new
|
|
202
|
+
// midpoint vertex, and the triangle index.
|
|
203
|
+
// Shall silently drop any new segments with an epsilon larger than the
|
|
204
|
+
// given one. This means that the segment shall be in the triangle mesh,
|
|
205
|
+
// but will not be queued and therefore not subdivided ever.
|
|
206
|
+
Arrugator.prototype._splitTriangle = function (v1, v2, vm, t, epsilon) {
|
|
207
|
+
if (epsilon === void 0) { epsilon = Infinity; }
|
|
208
|
+
var tvs = this._trigs[t];
|
|
209
|
+
var v3;
|
|
210
|
+
var winding = false;
|
|
211
|
+
// Fetch the ID of the 3rd vertex in the original triangle, and the winding order
|
|
212
|
+
if (tvs[0] === v1 && tvs[1] === v2) {
|
|
213
|
+
v3 = tvs[2];
|
|
214
|
+
winding = true; // A-B-C
|
|
215
|
+
}
|
|
216
|
+
else if (tvs[1] === v1 && tvs[2] === v2) {
|
|
217
|
+
v3 = tvs[0];
|
|
218
|
+
winding = true; // C-A-B
|
|
219
|
+
}
|
|
220
|
+
else if (tvs[2] === v1 && tvs[0] === v2) {
|
|
221
|
+
v3 = tvs[1];
|
|
222
|
+
winding = true; // B-C-A
|
|
223
|
+
}
|
|
224
|
+
else if (tvs[1] === v1 && tvs[0] === v2) {
|
|
225
|
+
v3 = tvs[2];
|
|
226
|
+
winding = false; // B-A-C
|
|
227
|
+
}
|
|
228
|
+
else if (tvs[2] === v1 && tvs[1] === v2) {
|
|
229
|
+
v3 = tvs[0];
|
|
230
|
+
winding = false; // C-B-A
|
|
231
|
+
}
|
|
232
|
+
else if (tvs[0] === v1 && tvs[2] === v2) {
|
|
233
|
+
v3 = tvs[1];
|
|
234
|
+
winding = false; // A-C-B
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
throw new Error('Data structure mishap: could not fetch 3rd vertex used in triangle');
|
|
238
|
+
}
|
|
239
|
+
// Index of the first "half" triangle will be the reused index of the original triangle
|
|
240
|
+
// Index of the second "half" triangle must be allocated at the end of the triangles structure
|
|
241
|
+
var t2 = this._trigs.length;
|
|
242
|
+
if (winding) {
|
|
243
|
+
this._trigs[t] = [v1, vm, v3];
|
|
244
|
+
this._trigs[t2] = [vm, v2, v3];
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
this._trigs[t] = [vm, v1, v3];
|
|
248
|
+
this._trigs[t2] = [v2, vm, v3];
|
|
249
|
+
}
|
|
250
|
+
// Clean up references from old segments
|
|
251
|
+
var s1 = this._vertToSeg[v1] && this._vertToSeg[v1][v2];
|
|
252
|
+
var s2 = this._vertToSeg[v2] && this._vertToSeg[v2][v3];
|
|
253
|
+
var s3 = this._vertToSeg[v3] && this._vertToSeg[v3][v1];
|
|
254
|
+
function filterTrig(i) {
|
|
255
|
+
return i !== t;
|
|
256
|
+
}
|
|
257
|
+
if (s1 !== undefined) {
|
|
258
|
+
this._segTrigs[s1] = this._segTrigs[s1].filter(filterTrig);
|
|
259
|
+
}
|
|
260
|
+
if (s2 !== undefined) {
|
|
261
|
+
this._segTrigs[s2] = this._segTrigs[s2].filter(filterTrig);
|
|
262
|
+
}
|
|
263
|
+
if (s3 !== undefined) {
|
|
264
|
+
this._segTrigs[s3] = this._segTrigs[s3].filter(filterTrig);
|
|
265
|
+
}
|
|
266
|
+
this._segment(v1, vm, t, epsilon);
|
|
267
|
+
this._segment(vm, v3, t, epsilon);
|
|
268
|
+
this._segment(v3, v1, t, epsilon);
|
|
269
|
+
this._segment(v2, vm, t2, epsilon);
|
|
270
|
+
this._segment(vm, v3, t2, epsilon);
|
|
271
|
+
this._segment(v3, v2, t2, epsilon);
|
|
272
|
+
};
|
|
273
|
+
return Arrugator;
|
|
274
|
+
}());
|
|
275
|
+
exports.default = Arrugator;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type Coordinates = [[number, number], [number, number], [number, number], [number, number]];
|
|
2
|
+
export type ArrugadoFlat = {
|
|
3
|
+
pos: number[];
|
|
4
|
+
uv: number[];
|
|
5
|
+
trigs: number[];
|
|
6
|
+
};
|
|
7
|
+
export declare function initArrugator(fromProj: string, coordinates: Coordinates, step?: number): ArrugadoFlat;
|
|
@@ -1,46 +1,49 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.initArrugator =
|
|
7
|
-
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// 墨卡托投影的左上角坐标,对应 mapbox 左上角起始坐标 [0,0]
|
|
12
|
-
var origin = [-20037508.342789244, 20037508.342789244];
|
|
13
|
-
// 坐标转换为 Arrugator 坐标 top-left, top-left, top-left, top-left)
|
|
14
|
-
var verts = [coordinates[0], coordinates[3], coordinates[1], coordinates[2]];
|
|
15
|
-
// 转换为 EPSG:3857
|
|
16
|
-
var projector = (0, proj4_1.default)(fromProj, 'EPSG:3857').forward;
|
|
17
|
-
// 改写坐标转换函数,因为 mapbox 的墨卡托坐标是 0-1,并且对应地理范围与标准 3857 不同
|
|
18
|
-
function forward(coors) {
|
|
19
|
-
// 墨卡托坐标
|
|
20
|
-
var coor_3857 = projector(coors);
|
|
21
|
-
// 墨卡托坐标转换到 0-1 区间,origin 对应 mapbox 0 0点
|
|
22
|
-
var mapbox_coor1 = Math.abs((coor_3857[0] - origin[0]) / (20037508.342789244 * 2));
|
|
23
|
-
var mapbox_coor2 = Math.abs((coor_3857[1] - origin[1]) / (20037508.342789244 * 2));
|
|
24
|
-
return [mapbox_coor1, mapbox_coor2];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
[0,
|
|
30
|
-
[
|
|
31
|
-
[1,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
[0,
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.initArrugator = initArrugator;
|
|
7
|
+
var proj4_1 = __importDefault(require("proj4"));
|
|
8
|
+
var Arrugator_1 = __importDefault(require("./Arrugator"));
|
|
9
|
+
function initArrugator(fromProj, coordinates, step) {
|
|
10
|
+
if (step === void 0) { step = 100; }
|
|
11
|
+
// 墨卡托投影的左上角坐标,对应 mapbox 左上角起始坐标 [0,0]
|
|
12
|
+
var origin = [-20037508.342789244, 20037508.342789244];
|
|
13
|
+
// 坐标转换为 Arrugator 坐标 top-left, top-left, top-left, top-left)
|
|
14
|
+
var verts = [coordinates[0], coordinates[3], coordinates[1], coordinates[2]];
|
|
15
|
+
// 转换为 EPSG:3857
|
|
16
|
+
var projector = (0, proj4_1.default)(fromProj, 'EPSG:3857').forward;
|
|
17
|
+
// 改写坐标转换函数,因为 mapbox 的墨卡托坐标是 0-1,并且对应地理范围与标准 3857 不同
|
|
18
|
+
function forward(coors) {
|
|
19
|
+
// 墨卡托坐标
|
|
20
|
+
var coor_3857 = projector(coors);
|
|
21
|
+
// 墨卡托坐标转换到 0-1 区间,origin 对应 mapbox 0 0点
|
|
22
|
+
var mapbox_coor1 = Math.abs((coor_3857[0] - origin[0]) / (20037508.342789244 * 2));
|
|
23
|
+
var mapbox_coor2 = Math.abs((coor_3857[1] - origin[1]) / (20037508.342789244 * 2));
|
|
24
|
+
return [mapbox_coor1, mapbox_coor2];
|
|
25
|
+
}
|
|
26
|
+
// 纹理uv坐标
|
|
27
|
+
var sourceUV = [
|
|
28
|
+
[0, 0], // top-left
|
|
29
|
+
[0, 1], // bottom-left
|
|
30
|
+
[1, 0], // top-right
|
|
31
|
+
[1, 1], // bottom-right
|
|
32
|
+
];
|
|
33
|
+
var arrugator = new Arrugator_1.default(forward, verts, sourceUV, [
|
|
34
|
+
[0, 1, 3],
|
|
35
|
+
[0, 3, 2],
|
|
36
|
+
]);
|
|
37
|
+
if (step > 0) {
|
|
38
|
+
arrugator.force();
|
|
39
|
+
for (var i = 0; i < step; i++) {
|
|
40
|
+
arrugator.step();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
var arrugado = arrugator.output();
|
|
44
|
+
return {
|
|
45
|
+
pos: arrugado.projected.flat(), // mapbox 墨卡托坐标
|
|
46
|
+
uv: arrugado.uv.flat(), // uv 纹理
|
|
47
|
+
trigs: arrugado.trigs.flat(), // 三角形索引
|
|
48
|
+
};
|
|
49
|
+
}
|
package/dist/js/index.d.ts
CHANGED
|
@@ -1,45 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
projection: string;
|
|
6
|
-
coordinates: Coordinates;
|
|
7
|
-
resampling?: 'linear' | 'nearest';
|
|
8
|
-
opacity?: number;
|
|
9
|
-
crossOrigin?: string;
|
|
10
|
-
};
|
|
11
|
-
export default class ImageLayer implements mapboxgl.CustomLayerInterface {
|
|
12
|
-
id: string;
|
|
13
|
-
type: 'custom';
|
|
14
|
-
renderingMode?: '2d' | '3d' | undefined;
|
|
15
|
-
private _option;
|
|
16
|
-
private _loaded;
|
|
17
|
-
private _arrugado;
|
|
18
|
-
private _map;
|
|
19
|
-
private _gl;
|
|
20
|
-
private _program;
|
|
21
|
-
private _texture;
|
|
22
|
-
private _positionBuffer;
|
|
23
|
-
private _uvBuffer;
|
|
24
|
-
private _verticesIndexBuffer;
|
|
25
|
-
constructor(id: string, option: ImageOption);
|
|
26
|
-
onAdd(map: mapboxgl.Map, gl: WebGLRenderingContext): void;
|
|
27
|
-
onRemove(map: mapboxgl.Map, gl: WebGLRenderingContext): void;
|
|
28
|
-
render(gl: WebGLRenderingContext, matrix: number[]): void;
|
|
29
|
-
/**
|
|
30
|
-
* Updates the image URL and, optionally, the projection, the coordinates and the resampling.
|
|
31
|
-
* @param {Object} option Options object.
|
|
32
|
-
* @param {string} [option.url] Required image URL.
|
|
33
|
-
* @param {string} [option.projection] Projection with EPSG code that points to the image..
|
|
34
|
-
* @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
|
|
35
|
-
* @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
|
|
36
|
-
*/
|
|
37
|
-
updateImage(option: {
|
|
38
|
-
url: string;
|
|
39
|
-
projection?: string;
|
|
40
|
-
coordinates?: Coordinates;
|
|
41
|
-
resampling?: 'linear' | 'nearest';
|
|
42
|
-
}): this;
|
|
43
|
-
private _bindData;
|
|
44
|
-
private _loadImage;
|
|
45
|
-
}
|
|
1
|
+
import ImageLayer from './ImageLayer';
|
|
2
|
+
export type { ImageOption, MaskProperty } from './ImageLayer';
|
|
3
|
+
export default ImageLayer;
|
|
4
|
+
export type { Coordinates } from './arrugator';
|
package/dist/js/index.js
CHANGED
|
@@ -1,134 +1,7 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
this.id = id;
|
|
9
|
-
this.type = 'custom';
|
|
10
|
-
this.renderingMode = '2d';
|
|
11
|
-
this._option = option;
|
|
12
|
-
this._loaded = false;
|
|
13
|
-
// 初始化 Arrugator
|
|
14
|
-
var projection = option.projection, coordinates = option.coordinates;
|
|
15
|
-
this._arrugado = (0, arrugator_1.initArrugator)(projection, coordinates);
|
|
16
|
-
this._map = null;
|
|
17
|
-
this._gl = null;
|
|
18
|
-
this._program = null;
|
|
19
|
-
this._texture = null;
|
|
20
|
-
this._positionBuffer = null;
|
|
21
|
-
this._uvBuffer = null;
|
|
22
|
-
this._verticesIndexBuffer = null;
|
|
23
|
-
}
|
|
24
|
-
ImageLayer.prototype.onAdd = function (map, gl) {
|
|
25
|
-
this._map = map;
|
|
26
|
-
this._gl = gl;
|
|
27
|
-
this._loadImage(map, gl);
|
|
28
|
-
var vertexSource = "\n uniform mat4 u_matrix;\n attribute vec2 a_pos;\n attribute vec2 a_uv;\n varying vec2 v_uv;\n void main() {\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n v_uv = a_uv;\n }";
|
|
29
|
-
var fragmentSource = "\n #ifdef GL_ES\n precision highp int;\n precision mediump float;\n #endif\n uniform sampler2D u_sampler;\n uniform float u_opacity;\n varying vec2 v_uv;\n void main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n }";
|
|
30
|
-
this._program = (0, webgl_1.createProgram)(gl, vertexSource, fragmentSource);
|
|
31
|
-
if (this._program) {
|
|
32
|
-
this._positionBuffer = gl.createBuffer();
|
|
33
|
-
// gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer)
|
|
34
|
-
// gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._arrugado.pos), gl.STATIC_DRAW)
|
|
35
|
-
var a_pos = gl.getAttribLocation(this._program, 'a_pos');
|
|
36
|
-
gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);
|
|
37
|
-
gl.enableVertexAttribArray(a_pos);
|
|
38
|
-
this._uvBuffer = gl.createBuffer();
|
|
39
|
-
// gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer)
|
|
40
|
-
// gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._arrugado.uv), gl.STATIC_DRAW)
|
|
41
|
-
var a_uv = gl.getAttribLocation(this._program, 'a_uv');
|
|
42
|
-
gl.vertexAttribPointer(a_uv, 2, gl.FLOAT, false, 0, 0);
|
|
43
|
-
gl.enableVertexAttribArray(a_uv);
|
|
44
|
-
this._verticesIndexBuffer = gl.createBuffer();
|
|
45
|
-
// gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer)
|
|
46
|
-
// gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this._arrugado.trigs), gl.STATIC_DRAW)
|
|
47
|
-
this._bindData(gl, this._arrugado);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
ImageLayer.prototype.onRemove = function (map, gl) {
|
|
51
|
-
gl.deleteProgram(this._program);
|
|
52
|
-
gl.deleteTexture(this._texture);
|
|
53
|
-
gl.deleteBuffer(this._verticesIndexBuffer);
|
|
54
|
-
};
|
|
55
|
-
ImageLayer.prototype.render = function (gl, matrix) {
|
|
56
|
-
if (this._loaded && this._program) {
|
|
57
|
-
gl.useProgram(this._program);
|
|
58
|
-
// matrix
|
|
59
|
-
gl.uniformMatrix4fv(gl.getUniformLocation(this._program, 'u_matrix'), false, matrix);
|
|
60
|
-
// pos
|
|
61
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
|
|
62
|
-
gl.vertexAttribPointer(gl.getAttribLocation(this._program, 'a_pos'), 2, gl.FLOAT, false, 0, 0);
|
|
63
|
-
// uv
|
|
64
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
|
|
65
|
-
gl.vertexAttribPointer(gl.getAttribLocation(this._program, 'a_uv'), 2, gl.FLOAT, false, 0, 0);
|
|
66
|
-
// index
|
|
67
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer);
|
|
68
|
-
// texture
|
|
69
|
-
gl.activeTexture(gl.TEXTURE0);
|
|
70
|
-
gl.bindTexture(gl.TEXTURE_2D, this._texture);
|
|
71
|
-
gl.uniform1i(gl.getUniformLocation(this._program, 'u_sampler'), 0);
|
|
72
|
-
// opacity
|
|
73
|
-
gl.uniform1f(gl.getUniformLocation(this._program, 'u_opacity'), this._option.opacity || 1);
|
|
74
|
-
// blend
|
|
75
|
-
gl.enable(gl.BLEND);
|
|
76
|
-
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
77
|
-
gl.drawElements(gl.TRIANGLES, this._arrugado.trigs.length, gl.UNSIGNED_SHORT, 0);
|
|
78
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
79
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Updates the image URL and, optionally, the projection, the coordinates and the resampling.
|
|
84
|
-
* @param {Object} option Options object.
|
|
85
|
-
* @param {string} [option.url] Required image URL.
|
|
86
|
-
* @param {string} [option.projection] Projection with EPSG code that points to the image..
|
|
87
|
-
* @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
|
|
88
|
-
* @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
|
|
89
|
-
*/
|
|
90
|
-
ImageLayer.prototype.updateImage = function (option) {
|
|
91
|
-
var _a, _b, _c;
|
|
92
|
-
this._loaded = false;
|
|
93
|
-
this._option.url = option.url;
|
|
94
|
-
if (this._gl && this._map) {
|
|
95
|
-
if (option.projection || option.coordinates) {
|
|
96
|
-
this._option.projection = (_a = option.projection) !== null && _a !== void 0 ? _a : this._option.projection;
|
|
97
|
-
this._option.coordinates = (_b = option.coordinates) !== null && _b !== void 0 ? _b : this._option.coordinates;
|
|
98
|
-
// reinit arrugator
|
|
99
|
-
this._arrugado = (0, arrugator_1.initArrugator)(this._option.projection, this._option.coordinates);
|
|
100
|
-
this._bindData(this._gl, this._arrugado);
|
|
101
|
-
}
|
|
102
|
-
this._option.resampling = (_c = option.resampling) !== null && _c !== void 0 ? _c : this._option.resampling;
|
|
103
|
-
// reload image
|
|
104
|
-
this._loadImage(this._map, this._gl);
|
|
105
|
-
}
|
|
106
|
-
return this;
|
|
107
|
-
};
|
|
108
|
-
ImageLayer.prototype._bindData = function (gl, arrugado) {
|
|
109
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
|
|
110
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrugado.pos), gl.STATIC_DRAW);
|
|
111
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
|
|
112
|
-
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrugado.uv), gl.STATIC_DRAW);
|
|
113
|
-
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer);
|
|
114
|
-
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(arrugado.trigs), gl.STATIC_DRAW);
|
|
115
|
-
};
|
|
116
|
-
ImageLayer.prototype._loadImage = function (map, gl) {
|
|
117
|
-
var _this = this;
|
|
118
|
-
(0, image_1.loadImage)(this._option.url, this._option.crossOrigin).then(function (img) {
|
|
119
|
-
_this._loaded = true;
|
|
120
|
-
// 创建纹理
|
|
121
|
-
_this._texture = gl.createTexture();
|
|
122
|
-
gl.bindTexture(gl.TEXTURE_2D, _this._texture);
|
|
123
|
-
var textureFilter = _this._option.resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
|
|
124
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, textureFilter);
|
|
125
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, textureFilter);
|
|
126
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
127
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
128
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
|
|
129
|
-
map.triggerRepaint();
|
|
130
|
-
});
|
|
131
|
-
};
|
|
132
|
-
return ImageLayer;
|
|
133
|
-
}());
|
|
134
|
-
exports.default = ImageLayer;
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
var ImageLayer_1 = __importDefault(require("./ImageLayer"));
|
|
7
|
+
exports.default = ImageLayer_1.default;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "\n#ifdef GL_ES\n precision highp int;\n precision mediump float;\n#endif\nuniform sampler2D u_sampler;\nuniform float u_opacity;\nvarying vec2 v_uv;\nvoid main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n}\n";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = "\n#ifdef GL_ES\n precision highp int;\n precision mediump float;\n#endif\nuniform sampler2D u_sampler;\nuniform float u_opacity;\nvarying vec2 v_uv;\nvoid main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n}\n";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = "\nuniform mat4 u_matrix;\nattribute vec2 a_pos;\nattribute vec2 a_uv;\nvarying vec2 v_uv;\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n v_uv = a_uv;\n}\n";
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: "\nuniform mat4 u_matrix;\nuniform float u_alt;\nattribute vec2 a_pos;\n\nconst float PI = 3.1415926536;\nconst float earthRadius = 6371008.8;\nconst float earthCircumference = 2.0 * PI * earthRadius; // meters\n\nfloat circumferenceAtLatitude(float latitude) {\n return earthCircumference * cos(latitude * PI / 180.0);\n}\n\nfloat mercatorXfromLng(float lng) {\n return (180.0 + lng) / 360.0;\n}\n\nfloat mercatorYfromLat(float lat) {\n return (180.0 - (180.0 / PI * log(tan(PI / 4.0 + lat * PI / 360.0)))) / 360.0;\n}\n\nfloat mercatorZfromAltitude(float altitude, float lat) {\n return altitude / circumferenceAtLatitude(lat);\n}\n\nvec3 mercatorfromLngLat(vec2 lnglat, float alt) {\n return vec3(mercatorXfromLng(lnglat.x), mercatorYfromLat(lnglat.y), mercatorZfromAltitude(alt, lnglat.y));\n}\n\nvoid main() {\n vec3 mercator = mercatorfromLngLat(a_pos, 0.0);\n gl_Position = u_matrix * vec4(mercator, 1.0);\n // gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n}\n";
|
|
2
|
+
export default _default;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = "\nuniform mat4 u_matrix;\nuniform float u_alt;\nattribute vec2 a_pos;\n\nconst float PI = 3.1415926536;\nconst float earthRadius = 6371008.8;\nconst float earthCircumference = 2.0 * PI * earthRadius; // meters\n\nfloat circumferenceAtLatitude(float latitude) {\n return earthCircumference * cos(latitude * PI / 180.0);\n}\n\nfloat mercatorXfromLng(float lng) {\n return (180.0 + lng) / 360.0;\n}\n\nfloat mercatorYfromLat(float lat) {\n return (180.0 - (180.0 / PI * log(tan(PI / 4.0 + lat * PI / 360.0)))) / 360.0;\n}\n\nfloat mercatorZfromAltitude(float altitude, float lat) {\n return altitude / circumferenceAtLatitude(lat);\n}\n\nvec3 mercatorfromLngLat(vec2 lnglat, float alt) {\n return vec3(mercatorXfromLng(lnglat.x), mercatorYfromLat(lnglat.y), mercatorZfromAltitude(alt, lnglat.y));\n}\n\nvoid main() {\n vec3 mercator = mercatorfromLngLat(a_pos, 0.0);\n gl_Position = u_matrix * vec4(mercator, 1.0);\n // gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n}\n";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naivemap/mapbox-gl-image-layer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-beta.0",
|
|
4
4
|
"description": "Load a static image of any projection via Arrugator and Proj4js.",
|
|
5
5
|
"author": "huanglii <li.huangli@qq.com>",
|
|
6
6
|
"homepage": "https://github.com/naivemap/mapbox-gl-layers#readme",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"proj4"
|
|
26
26
|
],
|
|
27
27
|
"publishConfig": {
|
|
28
|
-
"access": "public"
|
|
28
|
+
"access": "public",
|
|
29
|
+
"tag": "beta"
|
|
29
30
|
},
|
|
30
31
|
"repository": {
|
|
31
32
|
"type": "git",
|
|
@@ -45,13 +46,15 @@
|
|
|
45
46
|
"proj4": "^2.8.0"
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
|
-
"
|
|
49
|
+
"compare-versions": "^6.1.1",
|
|
50
|
+
"earcut": "^3.0.1",
|
|
51
|
+
"tinyqueue": "^3.0.0",
|
|
52
|
+
"twgl.js": "^5.5.4"
|
|
49
53
|
},
|
|
50
54
|
"devDependencies": {
|
|
55
|
+
"@types/earcut": "^2.1.1",
|
|
51
56
|
"@types/mapbox-gl": "^2.7.2",
|
|
52
|
-
"@types/node": "^17.0.36",
|
|
53
57
|
"@types/proj4": "^2.5.2",
|
|
54
58
|
"npm-run-all": "^4.1.5"
|
|
55
|
-
}
|
|
56
|
-
"gitHead": "5fc47667682399fe76c56d6808a44098bbd46636"
|
|
59
|
+
}
|
|
57
60
|
}
|