@naivemap/mapbox-gl-image-layer 0.6.0-beta.0 → 0.6.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.
@@ -1,62 +0,0 @@
1
- import mapboxgl from 'mapbox-gl';
2
- import type { Coordinates } from './arrugator';
3
- export type MaskProperty = {
4
- type?: 'in' | 'out';
5
- data: GeoJSON.Polygon | GeoJSON.MultiPolygon;
6
- };
7
- export type ImageOption = {
8
- url: string;
9
- projection: string;
10
- coordinates: Coordinates;
11
- resampling?: 'linear' | 'nearest';
12
- opacity?: number;
13
- crossOrigin?: string;
14
- arrugatorStep?: number;
15
- mask?: MaskProperty;
16
- metadata?: any;
17
- };
18
- export default class ImageLayer implements mapboxgl.CustomLayerInterface {
19
- id: string;
20
- type: 'custom';
21
- renderingMode?: '2d' | '3d' | undefined;
22
- metadata?: any;
23
- private option;
24
- private map?;
25
- private gl?;
26
- private loaded;
27
- private arrugado;
28
- private programInfo?;
29
- private bufferInfo?;
30
- private texture?;
31
- private stencilChecked;
32
- private maskProperty;
33
- private maskProgramInfo?;
34
- private maskBufferInfo?;
35
- constructor(id: string, option: ImageOption);
36
- onAdd(map: mapboxgl.Map, gl: WebGLRenderingContext): void;
37
- onRemove(_: mapboxgl.Map, gl: WebGLRenderingContext): void;
38
- render(gl: WebGLRenderingContext, matrix: number[]): void;
39
- /**
40
- * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
41
- * @param {Object} option Options object.
42
- * @param {string} [option.url] Image URL.
43
- * @param {string} [option.projection] Projection with EPSG code that points to the image..
44
- * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
45
- * @param {number} [option.opacity] opacity of the image.
46
- * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
47
- */
48
- updateImage(option: {
49
- url?: string;
50
- projection?: string;
51
- coordinates?: Coordinates;
52
- opacity?: number;
53
- resampling?: 'linear' | 'nearest';
54
- }): this;
55
- /**
56
- * Updates the mask property
57
- * @param {MaskProperty} mask The mask property.
58
- */
59
- updateMask(mask: Partial<MaskProperty>): this;
60
- private loadTexture;
61
- private getMaskBufferInfo;
62
- }
@@ -1,270 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- var compare_versions_1 = require("compare-versions");
40
- var earcut_1 = __importStar(require("earcut"));
41
- var mapbox_gl_1 = __importDefault(require("mapbox-gl"));
42
- var twgl = __importStar(require("twgl.js"));
43
- var arrugator_1 = require("./arrugator");
44
- var image_fragment_glsl_1 = __importDefault(require("./shaders/image.fragment.glsl"));
45
- var image_vertex_glsl_1 = __importDefault(require("./shaders/image.vertex.glsl"));
46
- var mask_fragment_glsl_1 = __importDefault(require("./shaders/mask.fragment.glsl"));
47
- var mask_vertex_glsl_1 = __importDefault(require("./shaders/mask.vertex.glsl"));
48
- var ImageLayer = /** @class */ (function () {
49
- function ImageLayer(id, option) {
50
- this.type = 'custom';
51
- this.renderingMode = '2d';
52
- // mask
53
- this.stencilChecked = true; // resetStencilClippingMasks 版本检查
54
- this.id = id;
55
- this.option = option;
56
- this.loaded = false;
57
- this.maskProperty = Object.assign({ type: 'in' }, option.mask);
58
- this.metadata = option.metadata;
59
- // 检查 stencil 是否可用
60
- this.stencilChecked = (0, compare_versions_1.satisfies)(mapbox_gl_1.default.version, '>=2.7.0');
61
- // 如果传了 mask 边界数据,且版本不符
62
- if (this.maskProperty.data && !this.stencilChecked) {
63
- throw new Error("\u5982\u679C\u9700\u8981\u906E\u7F69\uFF08\u63A9\u819C\uFF09\uFF0Cmapbox-gl \u7248\u672C\u5FC5\u987B\uFF1A>=2.7.0");
64
- }
65
- // 初始化 Arrugator
66
- var projection = option.projection, coordinates = option.coordinates;
67
- this.arrugado = (0, arrugator_1.initArrugator)(projection, coordinates, option.arrugatorStep);
68
- }
69
- ImageLayer.prototype.onAdd = function (map, gl) {
70
- this.map = map;
71
- this.gl = gl;
72
- // 主程序
73
- this.programInfo = twgl.createProgramInfo(gl, [image_vertex_glsl_1.default, image_fragment_glsl_1.default]);
74
- this.loadTexture(map, gl);
75
- this.bufferInfo = twgl.createBufferInfoFromArrays(gl, {
76
- a_pos: { numComponents: 2, data: this.arrugado.pos },
77
- a_uv: { numComponents: 2, data: this.arrugado.uv },
78
- indices: this.arrugado.trigs,
79
- });
80
- // 掩膜程序
81
- if (this.maskProperty.data) {
82
- var data = this.maskProperty.data;
83
- if (data) {
84
- this.maskProgramInfo = twgl.createProgramInfo(gl, [mask_vertex_glsl_1.default, mask_fragment_glsl_1.default]);
85
- this.maskBufferInfo = this.getMaskBufferInfo(gl, data);
86
- }
87
- }
88
- };
89
- ImageLayer.prototype.onRemove = function (_, gl) {
90
- if (this.programInfo) {
91
- gl.deleteProgram(this.programInfo.program);
92
- }
93
- if (this.maskProgramInfo) {
94
- gl.deleteProgram(this.maskProgramInfo.program);
95
- }
96
- if (this.texture) {
97
- gl.deleteTexture(this.texture);
98
- }
99
- };
100
- ImageLayer.prototype.render = function (gl, matrix) {
101
- /**
102
- * 线图层在启用 stencil 会消失,参考: https://github.com/mapbox/mapbox-gl-js/issues/12213
103
- * 临时解决方案: map.painter.resetStencilClippingMasks()
104
- * 该方法在 mapboxgl version >=2.7.0 才能用
105
- */
106
- var _a, _b;
107
- if (this.stencilChecked) {
108
- // @ts-ignore
109
- this.map.painter.resetStencilClippingMasks();
110
- }
111
- if (this.loaded && this.programInfo && this.bufferInfo) {
112
- // blend
113
- gl.enable(gl.BLEND);
114
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
115
- if (this.maskProgramInfo && this.maskBufferInfo) {
116
- // mask program
117
- gl.useProgram(this.maskProgramInfo.program);
118
- // stencil test
119
- gl.enable(gl.STENCIL_TEST);
120
- gl.stencilFunc(gl.ALWAYS, 1, 0xff);
121
- gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
122
- gl.stencilMask(0xff);
123
- gl.clear(gl.STENCIL_BUFFER_BIT);
124
- // matrix
125
- twgl.setUniforms(this.maskProgramInfo, { u_matrix: matrix });
126
- // pos & indices
127
- twgl.setBuffersAndAttributes(gl, this.maskProgramInfo, this.maskBufferInfo);
128
- // draw
129
- var elementType = gl.UNSIGNED_SHORT;
130
- if (this.maskBufferInfo.numElements / 3 > 65535) {
131
- // 使 drawElements 支持 UNSIGNED_INT 类型
132
- gl.getExtension('OES_element_index_uint');
133
- elementType = gl.UNSIGNED_INT;
134
- }
135
- gl.drawElements(gl.TRIANGLES, this.maskBufferInfo.numElements, elementType, 0);
136
- }
137
- // texture program
138
- gl.useProgram(this.programInfo.program);
139
- if ((_a = this.maskProgramInfo) === null || _a === void 0 ? void 0 : _a.program) {
140
- // stencil test
141
- var ref = this.maskProperty.type === 'out' ? 0 : 1;
142
- gl.stencilFunc(gl.EQUAL, ref, 0xff);
143
- gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
144
- }
145
- // uniforms
146
- twgl.setUniforms(this.programInfo, {
147
- u_matrix: matrix,
148
- u_opacity: (_b = this.option.opacity) !== null && _b !== void 0 ? _b : 1,
149
- u_sampler: this.texture,
150
- });
151
- // pos, uv & indices
152
- twgl.setBuffersAndAttributes(gl, this.programInfo, this.bufferInfo);
153
- // draw
154
- gl.drawElements(gl.TRIANGLES, this.arrugado.trigs.length, gl.UNSIGNED_SHORT, 0);
155
- gl.clear(gl.STENCIL_BUFFER_BIT);
156
- gl.disable(gl.STENCIL_TEST);
157
- }
158
- };
159
- /**
160
- * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
161
- * @param {Object} option Options object.
162
- * @param {string} [option.url] Image URL.
163
- * @param {string} [option.projection] Projection with EPSG code that points to the image..
164
- * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
165
- * @param {number} [option.opacity] opacity of the image.
166
- * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
167
- */
168
- ImageLayer.prototype.updateImage = function (option) {
169
- var _a, _b, _c, _d, _e;
170
- if (this.gl && this.map) {
171
- this.option.opacity = (_a = option.opacity) !== null && _a !== void 0 ? _a : this.option.opacity;
172
- if (option.projection || option.coordinates) {
173
- this.option.projection = (_b = option.projection) !== null && _b !== void 0 ? _b : this.option.projection;
174
- this.option.coordinates = (_c = option.coordinates) !== null && _c !== void 0 ? _c : this.option.coordinates;
175
- // reinit arrugator
176
- this.arrugado = (0, arrugator_1.initArrugator)(this.option.projection, this.option.coordinates, this.option.arrugatorStep);
177
- this.bufferInfo = twgl.createBufferInfoFromArrays(this.gl, {
178
- a_pos: { numComponents: 2, data: this.arrugado.pos },
179
- a_uv: { numComponents: 2, data: this.arrugado.uv },
180
- indices: this.arrugado.trigs,
181
- });
182
- }
183
- if (option.url || option.resampling) {
184
- this.loaded = false;
185
- this.option.url = (_d = option.url) !== null && _d !== void 0 ? _d : this.option.url;
186
- this.option.resampling = (_e = option.resampling) !== null && _e !== void 0 ? _e : this.option.resampling;
187
- // reload image
188
- this.loadTexture(this.map, this.gl);
189
- }
190
- else {
191
- this.map.triggerRepaint();
192
- }
193
- }
194
- return this;
195
- };
196
- /**
197
- * Updates the mask property
198
- * @param {MaskProperty} mask The mask property.
199
- */
200
- ImageLayer.prototype.updateMask = function (mask) {
201
- if (this.gl && this.map) {
202
- if (mask.data) {
203
- if (!this.maskProgramInfo) {
204
- this.maskProgramInfo = twgl.createProgramInfo(this.gl, [mask_vertex_glsl_1.default, mask_fragment_glsl_1.default]);
205
- }
206
- this.maskProperty = Object.assign(this.maskProperty, mask);
207
- this.maskBufferInfo = this.getMaskBufferInfo(this.gl, this.maskProperty.data);
208
- }
209
- else {
210
- this.maskProgramInfo && this.gl.deleteProgram(this.maskProgramInfo.program);
211
- this.maskProgramInfo = undefined;
212
- this.maskBufferInfo = undefined;
213
- }
214
- this.map.triggerRepaint();
215
- }
216
- return this;
217
- };
218
- ImageLayer.prototype.loadTexture = function (map, gl) {
219
- var _this = this;
220
- // 创建纹理
221
- var filter = this.option.resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
222
- this.texture = twgl.createTexture(gl, {
223
- src: this.option.url,
224
- crossOrigin: this.option.crossOrigin,
225
- minMag: filter,
226
- flipY: 0,
227
- }, function () {
228
- _this.loaded = true;
229
- map.triggerRepaint();
230
- });
231
- };
232
- ImageLayer.prototype.getMaskBufferInfo = function (gl, data) {
233
- var positions = [];
234
- var triangles = [];
235
- if (data.type === 'MultiPolygon') {
236
- // type: 'MultiPolygon'
237
- var polyCount = data.coordinates.length;
238
- var triangleStartIndex_1 = 0;
239
- for (var i = 0; i < polyCount; i++) {
240
- var coordinates = data.coordinates[i];
241
- var flattened = (0, earcut_1.flatten)(coordinates);
242
- var vertices = flattened.vertices, holes = flattened.holes, dimensions = flattened.dimensions;
243
- var triangle = (0, earcut_1.default)(vertices, holes, dimensions);
244
- var triangleNew = triangle.map(function (item) { return item + triangleStartIndex_1; });
245
- triangleStartIndex_1 += vertices.length / 2;
246
- // positions.push(...vertices)
247
- // triangles.push(...triangleNew)
248
- for (var m = 0; m < vertices.length; m++) {
249
- positions.push(vertices[m]);
250
- }
251
- for (var n = 0; n < triangleNew.length; n++) {
252
- triangles.push(triangleNew[n]);
253
- }
254
- }
255
- }
256
- else {
257
- // type: 'Polygon'
258
- var flattened = (0, earcut_1.flatten)(data.coordinates);
259
- var vertices = flattened.vertices, holes = flattened.holes, dimensions = flattened.dimensions;
260
- positions = vertices;
261
- triangles = (0, earcut_1.default)(vertices, holes, dimensions);
262
- }
263
- return twgl.createBufferInfoFromArrays(gl, {
264
- a_pos: { numComponents: 2, data: positions },
265
- indices: triangles.length / 3 > 65535 ? new Uint32Array(triangles) : new Uint16Array(triangles),
266
- });
267
- };
268
- return ImageLayer;
269
- }());
270
- exports.default = ImageLayer;
@@ -1,18 +0,0 @@
1
- export default class Arrugator {
2
- constructor(projector: any, verts: any, uv: any, trigs: any);
3
- _segment(v1: any, v2: any, t: any, maxEpsilon?: number): any;
4
- output(): {
5
- unprojected: unknown[];
6
- projected: unknown[];
7
- uv: unknown[];
8
- trigs: unknown[];
9
- };
10
- private _stepsWithSameEpsilon;
11
- lowerEpsilon(targetEpsilon: any): void;
12
- get epsilon(): any;
13
- set epsilon(ep: any);
14
- step(): void;
15
- force(): void;
16
- private _splitSegment;
17
- private _splitTriangle;
18
- }
@@ -1,275 +0,0 @@
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;
@@ -1,7 +0,0 @@
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,49 +0,0 @@
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
- }