ol 7.0.0-dev.1658443472213 → 7.0.0-dev.1658733468997

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.
Files changed (73) hide show
  1. package/Overlay.d.ts +3 -25
  2. package/Overlay.d.ts.map +1 -1
  3. package/Overlay.js +3 -25
  4. package/Overlay.js.map +1 -1
  5. package/package.json +2 -1
  6. package/render/webgl/BatchRenderer.d.ts +92 -0
  7. package/render/webgl/BatchRenderer.d.ts.map +1 -0
  8. package/render/webgl/BatchRenderer.js +165 -0
  9. package/render/webgl/BatchRenderer.js.map +1 -0
  10. package/render/webgl/LineStringBatchRenderer.d.ts +27 -0
  11. package/render/webgl/LineStringBatchRenderer.d.ts.map +1 -0
  12. package/render/webgl/LineStringBatchRenderer.js +114 -0
  13. package/render/webgl/LineStringBatchRenderer.js.map +1 -0
  14. package/render/webgl/MixedGeometryBatch.d.ts +306 -0
  15. package/render/webgl/MixedGeometryBatch.d.ts.map +1 -0
  16. package/render/webgl/MixedGeometryBatch.js +342 -0
  17. package/render/webgl/MixedGeometryBatch.js.map +1 -0
  18. package/render/webgl/PointBatchRenderer.d.ts +26 -0
  19. package/render/webgl/PointBatchRenderer.d.ts.map +1 -0
  20. package/render/webgl/PointBatchRenderer.js +102 -0
  21. package/render/webgl/PointBatchRenderer.js.map +1 -0
  22. package/render/webgl/PolygonBatchRenderer.d.ts +25 -0
  23. package/render/webgl/PolygonBatchRenderer.d.ts.map +1 -0
  24. package/render/webgl/PolygonBatchRenderer.js +110 -0
  25. package/render/webgl/PolygonBatchRenderer.js.map +1 -0
  26. package/render/webgl/constants.d.ts +43 -0
  27. package/render/webgl/constants.d.ts.map +1 -0
  28. package/render/webgl/constants.js +26 -0
  29. package/render/webgl/constants.js.map +1 -0
  30. package/render/webgl/utils.d.ts +76 -0
  31. package/render/webgl/utils.d.ts.map +1 -0
  32. package/render/webgl/utils.js +257 -0
  33. package/render/webgl/utils.js.map +1 -0
  34. package/renderer/webgl/Layer.d.ts +0 -98
  35. package/renderer/webgl/Layer.d.ts.map +1 -1
  36. package/renderer/webgl/Layer.js +0 -134
  37. package/renderer/webgl/Layer.js.map +1 -1
  38. package/renderer/webgl/PointsLayer.d.ts +4 -1
  39. package/renderer/webgl/PointsLayer.d.ts.map +1 -1
  40. package/renderer/webgl/PointsLayer.js +15 -8
  41. package/renderer/webgl/PointsLayer.js.map +1 -1
  42. package/renderer/webgl/TileLayer.js +1 -1
  43. package/renderer/webgl/TileLayer.js.map +1 -1
  44. package/renderer/webgl/VectorLayer.d.ts +142 -0
  45. package/renderer/webgl/VectorLayer.d.ts.map +1 -0
  46. package/renderer/webgl/VectorLayer.js +304 -0
  47. package/renderer/webgl/VectorLayer.js.map +1 -0
  48. package/renderer/webgl/shaders.d.ts +43 -0
  49. package/renderer/webgl/shaders.d.ts.map +1 -0
  50. package/renderer/webgl/shaders.js +53 -0
  51. package/renderer/webgl/shaders.js.map +1 -0
  52. package/src/Overlay.js +3 -25
  53. package/src/render/webgl/BatchRenderer.js +201 -0
  54. package/src/render/webgl/LineStringBatchRenderer.js +116 -0
  55. package/src/render/webgl/MixedGeometryBatch.js +364 -0
  56. package/src/render/webgl/PointBatchRenderer.js +97 -0
  57. package/src/render/webgl/PolygonBatchRenderer.js +117 -0
  58. package/src/render/webgl/constants.js +27 -0
  59. package/src/render/webgl/utils.js +351 -0
  60. package/src/renderer/webgl/Layer.js +0 -160
  61. package/src/renderer/webgl/PointsLayer.js +16 -12
  62. package/src/renderer/webgl/TileLayer.js +1 -1
  63. package/src/renderer/webgl/VectorLayer.js +409 -0
  64. package/src/renderer/webgl/shaders.js +198 -0
  65. package/src/webgl/Helper.js +30 -45
  66. package/src/worker/webgl.js +1 -1
  67. package/util.js +1 -1
  68. package/webgl/Helper.d.ts +17 -25
  69. package/webgl/Helper.d.ts.map +1 -1
  70. package/webgl/Helper.js +29 -43
  71. package/webgl/Helper.js.map +1 -1
  72. package/worker/webgl.js +1 -1
  73. package/worker/webgl.js.map +1 -1
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @module ol/render/webgl/PointBatchRenderer
3
+ */
4
+
5
+ import AbstractBatchRenderer from './BatchRenderer.js';
6
+ import {AttributeType} from '../../webgl/Helper.js';
7
+ import {apply as applyTransform} from '../../transform.js';
8
+
9
+ /**
10
+ * Names of attributes made available to the vertex shader.
11
+ * Please note: changing these *will* break custom shaders!
12
+ * @enum {string}
13
+ */
14
+ export const Attributes = {
15
+ POSITION: 'a_position',
16
+ INDEX: 'a_index',
17
+ };
18
+
19
+ class PointBatchRenderer extends AbstractBatchRenderer {
20
+ /**
21
+ * @param {import("../../webgl/Helper.js").default} helper WebGL helper instance
22
+ * @param {Worker} worker WebGL worker instance
23
+ * @param {string} vertexShader Vertex shader
24
+ * @param {string} fragmentShader Fragment shader
25
+ * @param {Array<import('./BatchRenderer.js').CustomAttribute>} customAttributes List of custom attributes
26
+ */
27
+ constructor(helper, worker, vertexShader, fragmentShader, customAttributes) {
28
+ super(helper, worker, vertexShader, fragmentShader, customAttributes);
29
+
30
+ // vertices for point must hold both a position (x,y) and an index (their position in the quad)
31
+ this.attributes = [
32
+ {
33
+ name: Attributes.POSITION,
34
+ size: 2,
35
+ type: AttributeType.FLOAT,
36
+ },
37
+ {
38
+ name: Attributes.INDEX,
39
+ size: 1,
40
+ type: AttributeType.FLOAT,
41
+ },
42
+ ].concat(
43
+ customAttributes.map(function (attribute) {
44
+ return {
45
+ name: 'a_' + attribute.name,
46
+ size: 1,
47
+ type: AttributeType.FLOAT,
48
+ };
49
+ })
50
+ );
51
+ }
52
+
53
+ /**
54
+ * Render instructions for lines are structured like so:
55
+ * [ x0, y0, customAttr0, ... , xN, yN, customAttrN ]
56
+ * @param {import("./MixedGeometryBatch.js").PointGeometryBatch} batch Point geometry batch
57
+ * @override
58
+ */
59
+ generateRenderInstructions(batch) {
60
+ // here we anticipate the amount of render instructions for points:
61
+ // 2 instructions per vertex for position (x and y)
62
+ // + 1 instruction per vertex per custom attributes
63
+ const totalInstructionsCount =
64
+ (2 + this.customAttributes.length) * batch.geometriesCount;
65
+ if (
66
+ !batch.renderInstructions ||
67
+ batch.renderInstructions.length !== totalInstructionsCount
68
+ ) {
69
+ batch.renderInstructions = new Float32Array(totalInstructionsCount);
70
+ }
71
+
72
+ // loop on features to fill the render instructions
73
+ let batchEntry;
74
+ const tmpCoords = [];
75
+ let renderIndex = 0;
76
+ let value;
77
+ for (const featureUid in batch.entries) {
78
+ batchEntry = batch.entries[featureUid];
79
+ for (let i = 0, ii = batchEntry.flatCoordss.length; i < ii; i++) {
80
+ tmpCoords[0] = batchEntry.flatCoordss[i][0];
81
+ tmpCoords[1] = batchEntry.flatCoordss[i][1];
82
+ applyTransform(batch.renderInstructionsTransform, tmpCoords);
83
+
84
+ batch.renderInstructions[renderIndex++] = tmpCoords[0];
85
+ batch.renderInstructions[renderIndex++] = tmpCoords[1];
86
+
87
+ // pushing custom attributes
88
+ for (let j = 0, jj = this.customAttributes.length; j < jj; j++) {
89
+ value = this.customAttributes[j].callback(batchEntry.feature);
90
+ batch.renderInstructions[renderIndex++] = value;
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ export default PointBatchRenderer;
@@ -0,0 +1,117 @@
1
+ /**
2
+ * @module ol/render/webgl/PolygonBatchRenderer
3
+ */
4
+ import AbstractBatchRenderer from './BatchRenderer.js';
5
+ import {AttributeType} from '../../webgl/Helper.js';
6
+ import {transform2D} from '../../geom/flat/transform.js';
7
+
8
+ /**
9
+ * Names of attributes made available to the vertex shader.
10
+ * Please note: changing these *will* break custom shaders!
11
+ * @enum {string}
12
+ */
13
+ export const Attributes = {
14
+ POSITION: 'a_position',
15
+ };
16
+
17
+ class PolygonBatchRenderer extends AbstractBatchRenderer {
18
+ /**
19
+ * @param {import("../../webgl/Helper.js").default} helper WebGL helper instance
20
+ * @param {Worker} worker WebGL worker instance
21
+ * @param {string} vertexShader Vertex shader
22
+ * @param {string} fragmentShader Fragment shader
23
+ * @param {Array<import('./BatchRenderer.js').CustomAttribute>} customAttributes List of custom attributes
24
+ */
25
+ constructor(helper, worker, vertexShader, fragmentShader, customAttributes) {
26
+ super(helper, worker, vertexShader, fragmentShader, customAttributes);
27
+
28
+ // By default only a position attribute is required to render polygons
29
+ this.attributes = [
30
+ {
31
+ name: Attributes.POSITION,
32
+ size: 2,
33
+ type: AttributeType.FLOAT,
34
+ },
35
+ ].concat(
36
+ customAttributes.map(function (attribute) {
37
+ return {
38
+ name: 'a_' + attribute.name,
39
+ size: 1,
40
+ type: AttributeType.FLOAT,
41
+ };
42
+ })
43
+ );
44
+ }
45
+
46
+ /**
47
+ * Render instructions for polygons are structured like so:
48
+ * [ customAttr0, ..., customAttrN, numberOfRings, numberOfVerticesInRing0, ..., numberOfVerticesInRingN, x0, y0, ..., xN, yN, numberOfRings,... ]
49
+ * @param {import("./MixedGeometryBatch.js").PolygonGeometryBatch} batch Polygon geometry batch
50
+ * @override
51
+ */
52
+ generateRenderInstructions(batch) {
53
+ // here we anticipate the amount of render instructions for polygons:
54
+ // 2 instructions per vertex for position (x and y)
55
+ // + 1 instruction per polygon per custom attributes
56
+ // + 1 instruction per polygon (for vertices count in polygon)
57
+ // + 1 instruction per ring (for vertices count in ring)
58
+ const totalInstructionsCount =
59
+ 2 * batch.verticesCount +
60
+ (1 + this.customAttributes.length) * batch.geometriesCount +
61
+ batch.ringsCount;
62
+ if (
63
+ !batch.renderInstructions ||
64
+ batch.renderInstructions.length !== totalInstructionsCount
65
+ ) {
66
+ batch.renderInstructions = new Float32Array(totalInstructionsCount);
67
+ }
68
+
69
+ // loop on features to fill the render instructions
70
+ let batchEntry;
71
+ const flatCoords = [];
72
+ let renderIndex = 0;
73
+ let value;
74
+ for (const featureUid in batch.entries) {
75
+ batchEntry = batch.entries[featureUid];
76
+ for (let i = 0, ii = batchEntry.flatCoordss.length; i < ii; i++) {
77
+ flatCoords.length = batchEntry.flatCoordss[i].length;
78
+ transform2D(
79
+ batchEntry.flatCoordss[i],
80
+ 0,
81
+ flatCoords.length,
82
+ 2,
83
+ batch.renderInstructionsTransform,
84
+ flatCoords
85
+ );
86
+
87
+ // custom attributes
88
+ for (let k = 0, kk = this.customAttributes.length; k < kk; k++) {
89
+ value = this.customAttributes[k].callback(batchEntry.feature);
90
+ batch.renderInstructions[renderIndex++] = value;
91
+ }
92
+
93
+ // ring count
94
+ batch.renderInstructions[renderIndex++] =
95
+ batchEntry.ringsVerticesCounts[i].length;
96
+
97
+ // vertices count in each ring
98
+ for (
99
+ let j = 0, jj = batchEntry.ringsVerticesCounts[i].length;
100
+ j < jj;
101
+ j++
102
+ ) {
103
+ batch.renderInstructions[renderIndex++] =
104
+ batchEntry.ringsVerticesCounts[i][j];
105
+ }
106
+
107
+ // looping on points for positions
108
+ for (let j = 0, jj = flatCoords.length; j < jj; j += 2) {
109
+ batch.renderInstructions[renderIndex++] = flatCoords[j];
110
+ batch.renderInstructions[renderIndex++] = flatCoords[j + 1];
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+
117
+ export default PolygonBatchRenderer;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @module ol/render/webgl/constants
3
+ */
4
+
5
+ /**
6
+ * @enum {string}
7
+ */
8
+ export const WebGLWorkerMessageType = {
9
+ GENERATE_POLYGON_BUFFERS: 'GENERATE_POLYGON_BUFFERS',
10
+ GENERATE_POINT_BUFFERS: 'GENERATE_POINT_BUFFERS',
11
+ GENERATE_LINE_STRING_BUFFERS: 'GENERATE_LINE_STRING_BUFFERS',
12
+ };
13
+
14
+ /**
15
+ * @typedef {Object} WebGLWorkerGenerateBuffersMessage
16
+ * This message will trigger the generation of a vertex and an index buffer based on the given render instructions.
17
+ * When the buffers are generated, the worked will send a message of the same type to the main thread, with
18
+ * the generated buffers in it.
19
+ * Note that any addition properties present in the message *will* be sent back to the main thread.
20
+ * @property {number} id Message id; will be used both in request and response as a means of identification
21
+ * @property {WebGLWorkerMessageType} type Message type
22
+ * @property {ArrayBuffer} renderInstructions Polygon render instructions raw binary buffer.
23
+ * @property {number} [customAttributesCount] Amount of custom attributes count in the polygon render instructions.
24
+ * @property {ArrayBuffer} [vertexBuffer] Vertices array raw binary buffer (sent by the worker).
25
+ * @property {ArrayBuffer} [indexBuffer] Indices array raw binary buffer (sent by the worker).
26
+ * @property {import("../../transform").Transform} [renderInstructionsTransform] Transformation matrix used to project the instructions coordinates
27
+ */
@@ -0,0 +1,351 @@
1
+ /**
2
+ * @module ol/render/webgl/utils
3
+ */
4
+ import earcut from 'earcut';
5
+ import {apply as applyTransform} from '../../transform.js';
6
+ import {clamp} from '../../math.js';
7
+
8
+ const tmpArray_ = [];
9
+
10
+ /**
11
+ * An object holding positions both in an index and a vertex buffer.
12
+ * @typedef {Object} BufferPositions
13
+ * @property {number} vertexPosition Position in the vertex buffer
14
+ * @property {number} indexPosition Position in the index buffer
15
+ */
16
+ const bufferPositions_ = {vertexPosition: 0, indexPosition: 0};
17
+
18
+ function writePointVertex(buffer, pos, x, y, index) {
19
+ buffer[pos + 0] = x;
20
+ buffer[pos + 1] = y;
21
+ buffer[pos + 2] = index;
22
+ }
23
+
24
+ /**
25
+ * Pushes a quad (two triangles) based on a point geometry
26
+ * @param {Float32Array} instructions Array of render instructions for points.
27
+ * @param {number} elementIndex Index from which render instructions will be read.
28
+ * @param {Float32Array} vertexBuffer Buffer in the form of a typed array.
29
+ * @param {Uint32Array} indexBuffer Buffer in the form of a typed array.
30
+ * @param {number} customAttributesCount Amount of custom attributes for each element.
31
+ * @param {BufferPositions} [bufferPositions] Buffer write positions; if not specified, positions will be set at 0.
32
+ * @return {BufferPositions} New buffer positions where to write next
33
+ * @property {number} vertexPosition New position in the vertex buffer where future writes should start.
34
+ * @property {number} indexPosition New position in the index buffer where future writes should start.
35
+ * @private
36
+ */
37
+ export function writePointFeatureToBuffers(
38
+ instructions,
39
+ elementIndex,
40
+ vertexBuffer,
41
+ indexBuffer,
42
+ customAttributesCount,
43
+ bufferPositions
44
+ ) {
45
+ // This is for x, y and index
46
+ const baseVertexAttrsCount = 3;
47
+ const baseInstructionsCount = 2;
48
+ const stride = baseVertexAttrsCount + customAttributesCount;
49
+
50
+ const x = instructions[elementIndex + 0];
51
+ const y = instructions[elementIndex + 1];
52
+
53
+ // read custom numerical attributes on the feature
54
+ const customAttrs = tmpArray_;
55
+ customAttrs.length = customAttributesCount;
56
+ for (let i = 0; i < customAttrs.length; i++) {
57
+ customAttrs[i] = instructions[elementIndex + baseInstructionsCount + i];
58
+ }
59
+
60
+ let vPos = bufferPositions ? bufferPositions.vertexPosition : 0;
61
+ let iPos = bufferPositions ? bufferPositions.indexPosition : 0;
62
+ const baseIndex = vPos / stride;
63
+
64
+ // push vertices for each of the four quad corners (first standard then custom attributes)
65
+ writePointVertex(vertexBuffer, vPos, x, y, 0);
66
+ customAttrs.length &&
67
+ vertexBuffer.set(customAttrs, vPos + baseVertexAttrsCount);
68
+ vPos += stride;
69
+
70
+ writePointVertex(vertexBuffer, vPos, x, y, 1);
71
+ customAttrs.length &&
72
+ vertexBuffer.set(customAttrs, vPos + baseVertexAttrsCount);
73
+ vPos += stride;
74
+
75
+ writePointVertex(vertexBuffer, vPos, x, y, 2);
76
+ customAttrs.length &&
77
+ vertexBuffer.set(customAttrs, vPos + baseVertexAttrsCount);
78
+ vPos += stride;
79
+
80
+ writePointVertex(vertexBuffer, vPos, x, y, 3);
81
+ customAttrs.length &&
82
+ vertexBuffer.set(customAttrs, vPos + baseVertexAttrsCount);
83
+ vPos += stride;
84
+
85
+ indexBuffer[iPos++] = baseIndex;
86
+ indexBuffer[iPos++] = baseIndex + 1;
87
+ indexBuffer[iPos++] = baseIndex + 3;
88
+ indexBuffer[iPos++] = baseIndex + 1;
89
+ indexBuffer[iPos++] = baseIndex + 2;
90
+ indexBuffer[iPos++] = baseIndex + 3;
91
+
92
+ bufferPositions_.vertexPosition = vPos;
93
+ bufferPositions_.indexPosition = iPos;
94
+
95
+ return bufferPositions_;
96
+ }
97
+
98
+ /**
99
+ * Pushes a single quad to form a line segment; also includes a computation for the join angles with previous and next
100
+ * segment, in order to be able to offset the vertices correctly in the shader
101
+ * @param {Float32Array} instructions Array of render instructions for lines.
102
+ * @param {number} segmentStartIndex Index of the segment start point from which render instructions will be read.
103
+ * @param {number} segmentEndIndex Index of the segment start point from which render instructions will be read.
104
+ * @param {number|null} beforeSegmentIndex Index of the point right before the segment (null if none, e.g this is a line start)
105
+ * @param {number|null} afterSegmentIndex Index of the point right after the segment (null if none, e.g this is a line end)
106
+ * @param {Array<number>} vertexArray Array containing vertices.
107
+ * @param {Array<number>} indexArray Array containing indices.
108
+ * @param {Array<number>} customAttributes Array of custom attributes value
109
+ * @param {import('../../transform.js').Transform} instructionsTransform Transform matrix used to project coordinates in instructions
110
+ * @param {import('../../transform.js').Transform} invertInstructionsTransform Transform matrix used to project coordinates in instructions
111
+ * @private
112
+ */
113
+ export function writeLineSegmentToBuffers(
114
+ instructions,
115
+ segmentStartIndex,
116
+ segmentEndIndex,
117
+ beforeSegmentIndex,
118
+ afterSegmentIndex,
119
+ vertexArray,
120
+ indexArray,
121
+ customAttributes,
122
+ instructionsTransform,
123
+ invertInstructionsTransform
124
+ ) {
125
+ // compute the stride to determine how many vertices were already pushed
126
+ const baseVertexAttrsCount = 5; // base attributes: x0, y0, x1, y1, params (vertex number [0-3], join angle 1, join angle 2)
127
+ const stride = baseVertexAttrsCount + customAttributes.length;
128
+ const baseIndex = vertexArray.length / stride;
129
+
130
+ // The segment is composed of two positions called P0[x0, y0] and P1[x1, y1]
131
+ // Depending on whether there are points before and after the segment, its final shape
132
+ // will be different
133
+ const p0 = [
134
+ instructions[segmentStartIndex + 0],
135
+ instructions[segmentStartIndex + 1],
136
+ ];
137
+ const p1 = [instructions[segmentEndIndex], instructions[segmentEndIndex + 1]];
138
+
139
+ // to compute offsets from the line center we need to reproject
140
+ // coordinates back in world units and compute the length of the segment
141
+ const p0world = applyTransform(invertInstructionsTransform, [...p0]);
142
+ const p1world = applyTransform(invertInstructionsTransform, [...p1]);
143
+
144
+ function computeVertexParameters(vertexNumber, joinAngle1, joinAngle2) {
145
+ const shift = 10000;
146
+ const anglePrecision = 1500;
147
+ return (
148
+ Math.round(joinAngle1 * anglePrecision) +
149
+ Math.round(joinAngle2 * anglePrecision) * shift +
150
+ vertexNumber * shift * shift
151
+ );
152
+ }
153
+
154
+ // compute the angle between p0pA and p0pB
155
+ // returns a value in [0, 2PI]
156
+ function angleBetween(p0, pA, pB) {
157
+ const lenA = Math.sqrt(
158
+ (pA[0] - p0[0]) * (pA[0] - p0[0]) + (pA[1] - p0[1]) * (pA[1] - p0[1])
159
+ );
160
+ const tangentA = [(pA[0] - p0[0]) / lenA, (pA[1] - p0[1]) / lenA];
161
+ const orthoA = [-tangentA[1], tangentA[0]];
162
+ const lenB = Math.sqrt(
163
+ (pB[0] - p0[0]) * (pB[0] - p0[0]) + (pB[1] - p0[1]) * (pB[1] - p0[1])
164
+ );
165
+ const tangentB = [(pB[0] - p0[0]) / lenB, (pB[1] - p0[1]) / lenB];
166
+
167
+ // this angle can be clockwise or anticlockwise; hence the computation afterwards
168
+ const angle =
169
+ lenA === 0 || lenB === 0
170
+ ? 0
171
+ : Math.acos(
172
+ clamp(tangentB[0] * tangentA[0] + tangentB[1] * tangentA[1], -1, 1)
173
+ );
174
+ const isClockwise = tangentB[0] * orthoA[0] + tangentB[1] * orthoA[1] > 0;
175
+ return !isClockwise ? Math.PI * 2 - angle : angle;
176
+ }
177
+
178
+ const joinBefore = beforeSegmentIndex !== null;
179
+ const joinAfter = afterSegmentIndex !== null;
180
+
181
+ let angle0 = 0;
182
+ let angle1 = 0;
183
+
184
+ // add vertices and adapt offsets for P0 in case of join
185
+ if (joinBefore) {
186
+ // B for before
187
+ const pB = [
188
+ instructions[beforeSegmentIndex],
189
+ instructions[beforeSegmentIndex + 1],
190
+ ];
191
+ const pBworld = applyTransform(invertInstructionsTransform, [...pB]);
192
+ angle0 = angleBetween(p0world, p1world, pBworld);
193
+ }
194
+ // adapt offsets for P1 in case of join
195
+ if (joinAfter) {
196
+ // A for after
197
+ const pA = [
198
+ instructions[afterSegmentIndex],
199
+ instructions[afterSegmentIndex + 1],
200
+ ];
201
+ const pAworld = applyTransform(invertInstructionsTransform, [...pA]);
202
+ angle1 = angleBetween(p1world, p0world, pAworld);
203
+ }
204
+
205
+ // add main segment triangles
206
+ vertexArray.push(
207
+ p0[0],
208
+ p0[1],
209
+ p1[0],
210
+ p1[1],
211
+ computeVertexParameters(0, angle0, angle1)
212
+ );
213
+ vertexArray.push(...customAttributes);
214
+
215
+ vertexArray.push(
216
+ p0[0],
217
+ p0[1],
218
+ p1[0],
219
+ p1[1],
220
+ computeVertexParameters(1, angle0, angle1)
221
+ );
222
+ vertexArray.push(...customAttributes);
223
+
224
+ vertexArray.push(
225
+ p0[0],
226
+ p0[1],
227
+ p1[0],
228
+ p1[1],
229
+ computeVertexParameters(2, angle0, angle1)
230
+ );
231
+ vertexArray.push(...customAttributes);
232
+
233
+ vertexArray.push(
234
+ p0[0],
235
+ p0[1],
236
+ p1[0],
237
+ p1[1],
238
+ computeVertexParameters(3, angle0, angle1)
239
+ );
240
+ vertexArray.push(...customAttributes);
241
+
242
+ indexArray.push(
243
+ baseIndex,
244
+ baseIndex + 1,
245
+ baseIndex + 2,
246
+ baseIndex + 1,
247
+ baseIndex + 3,
248
+ baseIndex + 2
249
+ );
250
+ }
251
+
252
+ /**
253
+ * Pushes several triangles to form a polygon, including holes
254
+ * @param {Float32Array} instructions Array of render instructions for lines.
255
+ * @param {number} polygonStartIndex Index of the polygon start point from which render instructions will be read.
256
+ * @param {Array<number>} vertexArray Array containing vertices.
257
+ * @param {Array<number>} indexArray Array containing indices.
258
+ * @param {number} customAttributesCount Amount of custom attributes for each element.
259
+ * @return {number} Next polygon instructions index
260
+ * @private
261
+ */
262
+ export function writePolygonTrianglesToBuffers(
263
+ instructions,
264
+ polygonStartIndex,
265
+ vertexArray,
266
+ indexArray,
267
+ customAttributesCount
268
+ ) {
269
+ const instructionsPerVertex = 2; // x, y
270
+ const attributesPerVertex = 2 + customAttributesCount;
271
+ let instructionsIndex = polygonStartIndex;
272
+ const customAttributes = instructions.slice(
273
+ instructionsIndex,
274
+ instructionsIndex + customAttributesCount
275
+ );
276
+ instructionsIndex += customAttributesCount;
277
+ const ringsCount = instructions[instructionsIndex++];
278
+ let verticesCount = 0;
279
+ const holes = new Array(ringsCount - 1);
280
+ for (let i = 0; i < ringsCount; i++) {
281
+ verticesCount += instructions[instructionsIndex++];
282
+ if (i < ringsCount - 1) {
283
+ holes[i] = verticesCount;
284
+ }
285
+ }
286
+ const flatCoords = instructions.slice(
287
+ instructionsIndex,
288
+ instructionsIndex + verticesCount * instructionsPerVertex
289
+ );
290
+
291
+ // pushing to vertices and indices!! this is where the magic happens
292
+ const result = earcut(flatCoords, holes, instructionsPerVertex);
293
+ for (let i = 0; i < result.length; i++) {
294
+ indexArray.push(result[i] + vertexArray.length / attributesPerVertex);
295
+ }
296
+ for (let i = 0; i < flatCoords.length; i += 2) {
297
+ vertexArray.push(flatCoords[i], flatCoords[i + 1], ...customAttributes);
298
+ }
299
+
300
+ return instructionsIndex + verticesCount * instructionsPerVertex;
301
+ }
302
+
303
+ /**
304
+ * Returns a texture of 1x1 pixel, white
305
+ * @private
306
+ * @return {ImageData} Image data.
307
+ */
308
+ export function getBlankImageData() {
309
+ const canvas = document.createElement('canvas');
310
+ const image = canvas.getContext('2d').createImageData(1, 1);
311
+ image.data[0] = 255;
312
+ image.data[1] = 255;
313
+ image.data[2] = 255;
314
+ image.data[3] = 255;
315
+ return image;
316
+ }
317
+
318
+ /**
319
+ * Generates a color array based on a numerical id
320
+ * Note: the range for each component is 0 to 1 with 256 steps
321
+ * @param {number} id Id
322
+ * @param {Array<number>} [opt_array] Reusable array
323
+ * @return {Array<number>} Color array containing the encoded id
324
+ */
325
+ export function colorEncodeId(id, opt_array) {
326
+ const array = opt_array || [];
327
+ const radix = 256;
328
+ const divide = radix - 1;
329
+ array[0] = Math.floor(id / radix / radix / radix) / divide;
330
+ array[1] = (Math.floor(id / radix / radix) % radix) / divide;
331
+ array[2] = (Math.floor(id / radix) % radix) / divide;
332
+ array[3] = (id % radix) / divide;
333
+ return array;
334
+ }
335
+
336
+ /**
337
+ * Reads an id from a color-encoded array
338
+ * Note: the expected range for each component is 0 to 1 with 256 steps.
339
+ * @param {Array<number>} color Color array containing the encoded id
340
+ * @return {number} Decoded id
341
+ */
342
+ export function colorDecodeId(color) {
343
+ let id = 0;
344
+ const radix = 256;
345
+ const mult = radix - 1;
346
+ id += Math.round(color[0] * radix * radix * radix * mult);
347
+ id += Math.round(color[1] * radix * radix * mult);
348
+ id += Math.round(color[2] * radix * mult);
349
+ id += Math.round(color[3] * mult);
350
+ return id;
351
+ }