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,201 @@
1
+ /**
2
+ * @module ol/render/webgl/BatchRenderer
3
+ */
4
+ import {WebGLWorkerMessageType} from './constants.js';
5
+ import {abstract} from '../../util.js';
6
+ import {
7
+ create as createTransform,
8
+ makeInverse as makeInverseTransform,
9
+ multiply as multiplyTransform,
10
+ translate as translateTransform,
11
+ } from '../../transform.js';
12
+
13
+ /**
14
+ * @typedef {Object} CustomAttribute A description of a custom attribute to be passed on to the GPU, with a value different
15
+ * for each feature.
16
+ * @property {string} name Attribute name.
17
+ * @property {function(import("../../Feature").default):number} callback This callback computes the numerical value of the
18
+ * attribute for a given feature.
19
+ */
20
+
21
+ let workerMessageCounter = 0;
22
+
23
+ /**
24
+ * @classdesc Abstract class for batch renderers.
25
+ * Batch renderers are meant to render the geometries contained in a {@link module:ol/render/webgl/GeometryBatch}
26
+ * instance. They are responsible for generating render instructions and transforming them into WebGL buffers.
27
+ */
28
+ class AbstractBatchRenderer {
29
+ /**
30
+ * @param {import("../../webgl/Helper.js").default} helper WebGL helper instance
31
+ * @param {Worker} worker WebGL worker instance
32
+ * @param {string} vertexShader Vertex shader
33
+ * @param {string} fragmentShader Fragment shader
34
+ * @param {Array<CustomAttribute>} customAttributes List of custom attributes
35
+ */
36
+ constructor(helper, worker, vertexShader, fragmentShader, customAttributes) {
37
+ /**
38
+ * @type {import("../../webgl/Helper.js").default}
39
+ * @private
40
+ */
41
+ this.helper_ = helper;
42
+
43
+ /**
44
+ * @type {Worker}
45
+ * @private
46
+ */
47
+ this.worker_ = worker;
48
+
49
+ /**
50
+ * @type {WebGLProgram}
51
+ * @private
52
+ */
53
+ this.program_ = this.helper_.getProgram(fragmentShader, vertexShader);
54
+
55
+ /**
56
+ * A list of attributes used by the renderer.
57
+ * @type {Array<import('../../webgl/Helper.js').AttributeDescription>}
58
+ * @protected
59
+ */
60
+ this.attributes = [];
61
+
62
+ /**
63
+ * @type {Array<CustomAttribute>}
64
+ * @protected
65
+ */
66
+ this.customAttributes = customAttributes;
67
+ }
68
+
69
+ /**
70
+ * Rebuild rendering instructions and webgl buffers based on the provided frame state
71
+ * Note: this is a costly operation.
72
+ * @param {import("./MixedGeometryBatch.js").GeometryBatch} batch Geometry batch
73
+ * @param {import("../../PluggableMap").FrameState} frameState Frame state.
74
+ * @param {import("../../geom/Geometry.js").Type} geometryType Geometry type
75
+ * @param {function(): void} callback Function called once the render buffers are updated
76
+ */
77
+ rebuild(batch, frameState, geometryType, callback) {
78
+ // store transform for rendering instructions
79
+ batch.renderInstructionsTransform = this.helper_.makeProjectionTransform(
80
+ frameState,
81
+ createTransform()
82
+ );
83
+ this.generateRenderInstructions(batch);
84
+ this.generateBuffers_(batch, geometryType, callback);
85
+ }
86
+
87
+ /**
88
+ * Render the geometries in the batch. This will also update the current transform used for rendering according to
89
+ * the invert transform of the webgl buffers
90
+ * @param {import("./MixedGeometryBatch.js").GeometryBatch} batch Geometry batch
91
+ * @param {import("../../transform.js").Transform} currentTransform Transform
92
+ * @param {import("../../PluggableMap.js").FrameState} frameState Frame state.
93
+ * @param {number} offsetX X offset
94
+ */
95
+ render(batch, currentTransform, frameState, offsetX) {
96
+ // multiply the current projection transform with the invert of the one used to fill buffers
97
+ this.helper_.makeProjectionTransform(frameState, currentTransform);
98
+ translateTransform(currentTransform, offsetX, 0);
99
+ multiplyTransform(currentTransform, batch.invertVerticesBufferTransform);
100
+
101
+ // enable program, buffers and attributes
102
+ this.helper_.useProgram(this.program_, frameState);
103
+ this.helper_.bindBuffer(batch.verticesBuffer);
104
+ this.helper_.bindBuffer(batch.indicesBuffer);
105
+ this.helper_.enableAttributes(this.attributes);
106
+
107
+ const renderCount = batch.indicesBuffer.getSize();
108
+ this.helper_.drawElements(0, renderCount);
109
+ }
110
+
111
+ /**
112
+ * Rebuild rendering instructions based on the provided frame state
113
+ * This is specific to the geometry type and has to be implemented by subclasses.
114
+ * @param {import("./MixedGeometryBatch.js").GeometryBatch} batch Geometry batch
115
+ * @protected
116
+ */
117
+ generateRenderInstructions(batch) {
118
+ abstract();
119
+ }
120
+
121
+ /**
122
+ * Rebuild internal webgl buffers for rendering based on the current rendering instructions;
123
+ * This is asynchronous: webgl buffers wil _not_ be updated right away
124
+ * @param {import("./MixedGeometryBatch.js").GeometryBatch} batch Geometry batch
125
+ * @param {import("../../geom/Geometry.js").Type} geometryType Geometry type
126
+ * @param {function(): void} callback Function called once the render buffers are updated
127
+ * @private
128
+ */
129
+ generateBuffers_(batch, geometryType, callback) {
130
+ const messageId = workerMessageCounter++;
131
+
132
+ let messageType;
133
+ switch (geometryType) {
134
+ case 'Polygon':
135
+ messageType = WebGLWorkerMessageType.GENERATE_POLYGON_BUFFERS;
136
+ break;
137
+ case 'Point':
138
+ messageType = WebGLWorkerMessageType.GENERATE_POINT_BUFFERS;
139
+ break;
140
+ case 'LineString':
141
+ messageType = WebGLWorkerMessageType.GENERATE_LINE_STRING_BUFFERS;
142
+ break;
143
+ default:
144
+ // pass
145
+ }
146
+
147
+ /** @type {import('./constants.js').WebGLWorkerGenerateBuffersMessage} */
148
+ const message = {
149
+ id: messageId,
150
+ type: messageType,
151
+ renderInstructions: batch.renderInstructions.buffer,
152
+ renderInstructionsTransform: batch.renderInstructionsTransform,
153
+ customAttributesCount: this.customAttributes.length,
154
+ };
155
+ this.worker_.postMessage(message, [batch.renderInstructions.buffer]);
156
+
157
+ // leave ownership of render instructions
158
+ batch.renderInstructions = null;
159
+
160
+ const handleMessage =
161
+ /**
162
+ * @param {*} event Event.
163
+ * @this {AbstractBatchRenderer}
164
+ */
165
+ function (event) {
166
+ const received = event.data;
167
+
168
+ // this is not the response to our request: skip
169
+ if (received.id !== messageId) {
170
+ return;
171
+ }
172
+
173
+ // we've received our response: stop listening
174
+ this.worker_.removeEventListener('message', handleMessage);
175
+
176
+ // store transform & invert transform for webgl buffers
177
+ batch.verticesBufferTransform = received.renderInstructionsTransform;
178
+ makeInverseTransform(
179
+ batch.invertVerticesBufferTransform,
180
+ batch.verticesBufferTransform
181
+ );
182
+
183
+ // copy & flush received buffers to GPU
184
+ batch.verticesBuffer.fromArrayBuffer(received.vertexBuffer);
185
+ this.helper_.flushBufferData(batch.verticesBuffer);
186
+ batch.indicesBuffer.fromArrayBuffer(received.indexBuffer);
187
+ this.helper_.flushBufferData(batch.indicesBuffer);
188
+
189
+ // take back ownership of the render instructions for further use
190
+ batch.renderInstructions = new Float32Array(
191
+ received.renderInstructions
192
+ );
193
+
194
+ callback();
195
+ }.bind(this);
196
+
197
+ this.worker_.addEventListener('message', handleMessage);
198
+ }
199
+ }
200
+
201
+ export default AbstractBatchRenderer;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @module ol/render/webgl/LineStringBatchRenderer
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
+ SEGMENT_START: 'a_segmentStart',
15
+ SEGMENT_END: 'a_segmentEnd',
16
+ PARAMETERS: 'a_parameters',
17
+ };
18
+
19
+ class LineStringBatchRenderer 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 lines must hold both a position (x,y) and an offset (dx,dy)
31
+ this.attributes = [
32
+ {
33
+ name: Attributes.SEGMENT_START,
34
+ size: 2,
35
+ type: AttributeType.FLOAT,
36
+ },
37
+ {
38
+ name: Attributes.SEGMENT_END,
39
+ size: 2,
40
+ type: AttributeType.FLOAT,
41
+ },
42
+ {
43
+ name: Attributes.PARAMETERS,
44
+ size: 1,
45
+ type: AttributeType.FLOAT,
46
+ },
47
+ ].concat(
48
+ customAttributes.map(function (attribute) {
49
+ return {
50
+ name: 'a_' + attribute.name,
51
+ size: 1,
52
+ type: AttributeType.FLOAT,
53
+ };
54
+ })
55
+ );
56
+ }
57
+
58
+ /**
59
+ * Render instructions for lines are structured like so:
60
+ * [ customAttr0, ... , customAttrN, numberOfVertices0, x0, y0, ... , xN, yN, numberOfVertices1, ... ]
61
+ * @param {import("./MixedGeometryBatch.js").LineStringGeometryBatch} batch Linestring geometry batch
62
+ * @override
63
+ */
64
+ generateRenderInstructions(batch) {
65
+ // here we anticipate the amount of render instructions for lines:
66
+ // 2 instructions per vertex for position (x and y)
67
+ // + 1 instruction per line per custom attributes
68
+ // + 1 instruction per line (for vertices count)
69
+ const totalInstructionsCount =
70
+ 2 * batch.verticesCount +
71
+ (1 + this.customAttributes.length) * batch.geometriesCount;
72
+ if (
73
+ !batch.renderInstructions ||
74
+ batch.renderInstructions.length !== totalInstructionsCount
75
+ ) {
76
+ batch.renderInstructions = new Float32Array(totalInstructionsCount);
77
+ }
78
+
79
+ // loop on features to fill the render instructions
80
+ let batchEntry;
81
+ const flatCoords = [];
82
+ let renderIndex = 0;
83
+ let value;
84
+ for (const featureUid in batch.entries) {
85
+ batchEntry = batch.entries[featureUid];
86
+ for (let i = 0, ii = batchEntry.flatCoordss.length; i < ii; i++) {
87
+ flatCoords.length = batchEntry.flatCoordss[i].length;
88
+ transform2D(
89
+ batchEntry.flatCoordss[i],
90
+ 0,
91
+ flatCoords.length,
92
+ 2,
93
+ batch.renderInstructionsTransform,
94
+ flatCoords
95
+ );
96
+
97
+ // custom attributes
98
+ for (let k = 0, kk = this.customAttributes.length; k < kk; k++) {
99
+ value = this.customAttributes[k].callback(batchEntry.feature);
100
+ batch.renderInstructions[renderIndex++] = value;
101
+ }
102
+
103
+ // vertices count
104
+ batch.renderInstructions[renderIndex++] = flatCoords.length / 2;
105
+
106
+ // looping on points for positions
107
+ for (let j = 0, jj = flatCoords.length; j < jj; j += 2) {
108
+ batch.renderInstructions[renderIndex++] = flatCoords[j];
109
+ batch.renderInstructions[renderIndex++] = flatCoords[j + 1];
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+
116
+ export default LineStringBatchRenderer;
@@ -0,0 +1,364 @@
1
+ /**
2
+ * @module ol/render/webgl/MixedGeometryBatch
3
+ */
4
+ import WebGLArrayBuffer from '../../webgl/Buffer.js';
5
+ import {ARRAY_BUFFER, DYNAMIC_DRAW, ELEMENT_ARRAY_BUFFER} from '../../webgl.js';
6
+ import {create as createTransform} from '../../transform.js';
7
+ import {getUid} from '../../util.js';
8
+
9
+ /**
10
+ * @typedef {Object} GeometryBatchItem Object that holds a reference to a feature as well as the raw coordinates of its various geometries
11
+ * @property {import("../../Feature").default} feature Feature
12
+ * @property {Array<Array<number>>} flatCoordss Array of flat coordinates arrays, one for each geometry related to the feature
13
+ * @property {number} [verticesCount] Only defined for linestring and polygon batches
14
+ * @property {number} [ringsCount] Only defined for polygon batches
15
+ * @property {Array<Array<number>>} [ringsVerticesCounts] Array of vertices counts in each ring for each geometry; only defined for polygons batches
16
+ */
17
+
18
+ /**
19
+ * @typedef {PointGeometryBatch|LineStringGeometryBatch|PolygonGeometryBatch} GeometryBatch
20
+ */
21
+
22
+ /**
23
+ * @typedef {Object} PolygonGeometryBatch A geometry batch specific to polygons
24
+ * @property {Object<string, GeometryBatchItem>} entries Dictionary of all entries in the batch with associated computed values.
25
+ * One entry corresponds to one feature. Key is feature uid.
26
+ * @property {number} geometriesCount Amount of geometries in the batch.
27
+ * @property {Float32Array} renderInstructions Render instructions for polygons are structured like so:
28
+ * [ numberOfRings, numberOfVerticesInRing0, ..., numberOfVerticesInRingN, x0, y0, customAttr0, ..., xN, yN, customAttrN, numberOfRings,... ]
29
+ * @property {WebGLArrayBuffer} verticesBuffer Vertices WebGL buffer
30
+ * @property {WebGLArrayBuffer} indicesBuffer Indices WebGL buffer
31
+ * @property {import("../../transform.js").Transform} renderInstructionsTransform Converts world space coordinates to screen space; applies to the rendering instructions
32
+ * @property {import("../../transform.js").Transform} verticesBufferTransform Converts world space coordinates to screen space; applies to the webgl vertices buffer
33
+ * @property {import("../../transform.js").Transform} invertVerticesBufferTransform Screen space to world space; applies to the webgl vertices buffer
34
+ * @property {number} verticesCount Amount of vertices from geometries in the batch.
35
+ * @property {number} ringsCount How many outer and inner rings in this batch.
36
+ */
37
+
38
+ /**
39
+ * @typedef {Object} LineStringGeometryBatch A geometry batch specific to lines
40
+ * @property {Object<string, GeometryBatchItem>} entries Dictionary of all entries in the batch with associated computed values.
41
+ * One entry corresponds to one feature. Key is feature uid.
42
+ * @property {number} geometriesCount Amount of geometries in the batch.
43
+ * @property {Float32Array} renderInstructions Render instructions for polygons are structured like so:
44
+ * [ numberOfRings, numberOfVerticesInRing0, ..., numberOfVerticesInRingN, x0, y0, customAttr0, ..., xN, yN, customAttrN, numberOfRings,... ]
45
+ * @property {WebGLArrayBuffer} verticesBuffer Vertices WebGL buffer
46
+ * @property {WebGLArrayBuffer} indicesBuffer Indices WebGL buffer
47
+ * @property {import("../../transform.js").Transform} renderInstructionsTransform Converts world space coordinates to screen space; applies to the rendering instructions
48
+ * @property {import("../../transform.js").Transform} verticesBufferTransform Converts world space coordinates to screen space; applies to the webgl vertices buffer
49
+ * @property {import("../../transform.js").Transform} invertVerticesBufferTransform Screen space to world space; applies to the webgl vertices buffer
50
+ * @property {number} verticesCount Amount of vertices from geometries in the batch.
51
+ */
52
+
53
+ /**
54
+ * @typedef {Object} PointGeometryBatch A geometry batch specific to points
55
+ * @property {Object<string, GeometryBatchItem>} entries Dictionary of all entries in the batch with associated computed values.
56
+ * One entry corresponds to one feature. Key is feature uid.
57
+ * @property {number} geometriesCount Amount of geometries in the batch.
58
+ * @property {Float32Array} renderInstructions Render instructions for polygons are structured like so:
59
+ * [ numberOfRings, numberOfVerticesInRing0, ..., numberOfVerticesInRingN, x0, y0, customAttr0, ..., xN, yN, customAttrN, numberOfRings,... ]
60
+ * @property {WebGLArrayBuffer} verticesBuffer Vertices WebGL buffer
61
+ * @property {WebGLArrayBuffer} indicesBuffer Indices WebGL buffer
62
+ * @property {import("../../transform.js").Transform} renderInstructionsTransform Converts world space coordinates to screen space; applies to the rendering instructions
63
+ * @property {import("../../transform.js").Transform} verticesBufferTransform Converts world space coordinates to screen space; applies to the webgl vertices buffer
64
+ * @property {import("../../transform.js").Transform} invertVerticesBufferTransform Screen space to world space; applies to the webgl vertices buffer
65
+ */
66
+
67
+ /**
68
+ * @classdesc This class is used to group several geometries of various types together for faster rendering.
69
+ * Three inner batches are maintained for polygons, lines and points. Each time a feature is added, changed or removed
70
+ * from the batch, these inner batches are modified accordingly in order to keep them up-to-date.
71
+ *
72
+ * A feature can be present in several inner batches, for example a polygon geometry will be present in the polygon batch
73
+ * and its linar rings will be present in the line batch. Multi geometries are also broken down into individual geometries
74
+ * and added to the corresponding batches in a recursive manner.
75
+ *
76
+ * Corresponding {@link module:ol/render/webgl/BatchRenderer} instances are then used to generate the render instructions
77
+ * and WebGL buffers (vertices and indices) for each inner batches; render instructions are stored on the inner batches,
78
+ * alongside the transform used to convert world coords to screen coords at the time these instructions were generated.
79
+ * The resulting WebGL buffers are stored on the batches as well.
80
+ *
81
+ * An important aspect of geometry batches is that there is no guarantee that render instructions and WebGL buffers
82
+ * are synchronized, i.e. render instructions can describe a new state while WebGL buffers might not have been written yet.
83
+ * This is why two world-to-screen transforms are stored on each batch: one for the render instructions and one for
84
+ * the WebGL buffers.
85
+ */
86
+ class MixedGeometryBatch {
87
+ constructor() {
88
+ /**
89
+ * @type {PolygonGeometryBatch}
90
+ */
91
+ this.polygonBatch = {
92
+ entries: {},
93
+ geometriesCount: 0,
94
+ verticesCount: 0,
95
+ ringsCount: 0,
96
+ renderInstructions: new Float32Array(0),
97
+ verticesBuffer: new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW),
98
+ indicesBuffer: new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW),
99
+ renderInstructionsTransform: createTransform(),
100
+ verticesBufferTransform: createTransform(),
101
+ invertVerticesBufferTransform: createTransform(),
102
+ };
103
+
104
+ /**
105
+ * @type {PointGeometryBatch}
106
+ */
107
+ this.pointBatch = {
108
+ entries: {},
109
+ geometriesCount: 0,
110
+ renderInstructions: new Float32Array(0),
111
+ verticesBuffer: new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW),
112
+ indicesBuffer: new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW),
113
+ renderInstructionsTransform: createTransform(),
114
+ verticesBufferTransform: createTransform(),
115
+ invertVerticesBufferTransform: createTransform(),
116
+ };
117
+
118
+ /**
119
+ * @type {LineStringGeometryBatch}
120
+ */
121
+ this.lineStringBatch = {
122
+ entries: {},
123
+ geometriesCount: 0,
124
+ verticesCount: 0,
125
+ renderInstructions: new Float32Array(0),
126
+ verticesBuffer: new WebGLArrayBuffer(ARRAY_BUFFER, DYNAMIC_DRAW),
127
+ indicesBuffer: new WebGLArrayBuffer(ELEMENT_ARRAY_BUFFER, DYNAMIC_DRAW),
128
+ renderInstructionsTransform: createTransform(),
129
+ verticesBufferTransform: createTransform(),
130
+ invertVerticesBufferTransform: createTransform(),
131
+ };
132
+ }
133
+
134
+ /**
135
+ * @param {Array<import("../../Feature").default>} features Array of features to add to the batch
136
+ */
137
+ addFeatures(features) {
138
+ for (let i = 0; i < features.length; i++) {
139
+ this.addFeature(features[i]);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * @param {import("../../Feature").default} feature Feature to add to the batch
145
+ */
146
+ addFeature(feature) {
147
+ const geometry = feature.getGeometry();
148
+ if (!geometry) {
149
+ return;
150
+ }
151
+ this.addGeometry_(geometry, feature);
152
+ }
153
+
154
+ /**
155
+ * @param {import("../../Feature").default} feature Feature
156
+ * @return {GeometryBatchItem} Batch item added (or existing one)
157
+ * @private
158
+ */
159
+ addFeatureEntryInPointBatch_(feature) {
160
+ const uid = getUid(feature);
161
+ if (!(uid in this.pointBatch.entries)) {
162
+ this.pointBatch.entries[uid] = {
163
+ feature: feature,
164
+ flatCoordss: [],
165
+ };
166
+ }
167
+ return this.pointBatch.entries[uid];
168
+ }
169
+
170
+ /**
171
+ * @param {import("../../Feature").default} feature Feature
172
+ * @return {GeometryBatchItem} Batch item added (or existing one)
173
+ * @private
174
+ */
175
+ addFeatureEntryInLineStringBatch_(feature) {
176
+ const uid = getUid(feature);
177
+ if (!(uid in this.lineStringBatch.entries)) {
178
+ this.lineStringBatch.entries[uid] = {
179
+ feature: feature,
180
+ flatCoordss: [],
181
+ verticesCount: 0,
182
+ };
183
+ }
184
+ return this.lineStringBatch.entries[uid];
185
+ }
186
+
187
+ /**
188
+ * @param {import("../../Feature").default} feature Feature
189
+ * @return {GeometryBatchItem} Batch item added (or existing one)
190
+ * @private
191
+ */
192
+ addFeatureEntryInPolygonBatch_(feature) {
193
+ const uid = getUid(feature);
194
+ if (!(uid in this.polygonBatch.entries)) {
195
+ this.polygonBatch.entries[uid] = {
196
+ feature: feature,
197
+ flatCoordss: [],
198
+ verticesCount: 0,
199
+ ringsCount: 0,
200
+ ringsVerticesCounts: [],
201
+ };
202
+ }
203
+ return this.polygonBatch.entries[uid];
204
+ }
205
+
206
+ /**
207
+ * @param {import("../../Feature").default} feature Feature
208
+ * @private
209
+ */
210
+ clearFeatureEntryInPointBatch_(feature) {
211
+ const entry = this.pointBatch.entries[getUid(feature)];
212
+ if (!entry) {
213
+ return;
214
+ }
215
+ this.pointBatch.geometriesCount -= entry.flatCoordss.length;
216
+ delete this.pointBatch.entries[getUid(feature)];
217
+ }
218
+
219
+ /**
220
+ * @param {import("../../Feature").default} feature Feature
221
+ * @private
222
+ */
223
+ clearFeatureEntryInLineStringBatch_(feature) {
224
+ const entry = this.lineStringBatch.entries[getUid(feature)];
225
+ if (!entry) {
226
+ return;
227
+ }
228
+ this.lineStringBatch.verticesCount -= entry.verticesCount;
229
+ this.lineStringBatch.geometriesCount -= entry.flatCoordss.length;
230
+ delete this.lineStringBatch.entries[getUid(feature)];
231
+ }
232
+
233
+ /**
234
+ * @param {import("../../Feature").default} feature Feature
235
+ * @private
236
+ */
237
+ clearFeatureEntryInPolygonBatch_(feature) {
238
+ const entry = this.polygonBatch.entries[getUid(feature)];
239
+ if (!entry) {
240
+ return;
241
+ }
242
+ this.polygonBatch.verticesCount -= entry.verticesCount;
243
+ this.polygonBatch.ringsCount -= entry.ringsCount;
244
+ this.polygonBatch.geometriesCount -= entry.flatCoordss.length;
245
+ delete this.polygonBatch.entries[getUid(feature)];
246
+ }
247
+
248
+ /**
249
+ * @param {import("../../geom").Geometry} geometry Geometry
250
+ * @param {import("../../Feature").default} feature Feature
251
+ * @private
252
+ */
253
+ addGeometry_(geometry, feature) {
254
+ const type = geometry.getType();
255
+ let flatCoords;
256
+ let verticesCount;
257
+ let batchEntry;
258
+ switch (type) {
259
+ case 'GeometryCollection':
260
+ /** @type {import("../../geom").GeometryCollection} */ (geometry)
261
+ .getGeometries()
262
+ .map((geom) => this.addGeometry_(geom, feature));
263
+ break;
264
+ case 'MultiPolygon':
265
+ /** @type {import("../../geom").MultiPolygon} */ (geometry)
266
+ .getPolygons()
267
+ .map((polygon) => this.addGeometry_(polygon, feature));
268
+ break;
269
+ case 'MultiLineString':
270
+ /** @type {import("../../geom").MultiLineString} */ (geometry)
271
+ .getLineStrings()
272
+ .map((line) => this.addGeometry_(line, feature));
273
+ break;
274
+ case 'MultiPoint':
275
+ /** @type {import("../../geom").MultiPoint} */ (geometry)
276
+ .getPoints()
277
+ .map((point) => this.addGeometry_(point, feature));
278
+ break;
279
+ case 'Polygon':
280
+ const polygonGeom = /** @type {import("../../geom").Polygon} */ (
281
+ geometry
282
+ );
283
+ batchEntry = this.addFeatureEntryInPolygonBatch_(feature);
284
+ flatCoords = polygonGeom.getFlatCoordinates();
285
+ verticesCount = flatCoords.length / 2;
286
+ const ringsCount = polygonGeom.getLinearRingCount();
287
+ const ringsVerticesCount = polygonGeom
288
+ .getEnds()
289
+ .map((end, ind, arr) =>
290
+ ind > 0 ? (end - arr[ind - 1]) / 2 : end / 2
291
+ );
292
+ this.polygonBatch.verticesCount += verticesCount;
293
+ this.polygonBatch.ringsCount += ringsCount;
294
+ this.polygonBatch.geometriesCount++;
295
+ batchEntry.flatCoordss.push(flatCoords);
296
+ batchEntry.ringsVerticesCounts.push(ringsVerticesCount);
297
+ batchEntry.verticesCount += verticesCount;
298
+ batchEntry.ringsCount += ringsCount;
299
+ polygonGeom
300
+ .getLinearRings()
301
+ .map((ring) => this.addGeometry_(ring, feature));
302
+ break;
303
+ case 'Point':
304
+ const pointGeom = /** @type {import("../../geom").Point} */ (geometry);
305
+ batchEntry = this.addFeatureEntryInPointBatch_(feature);
306
+ flatCoords = pointGeom.getFlatCoordinates();
307
+ this.pointBatch.geometriesCount++;
308
+ batchEntry.flatCoordss.push(flatCoords);
309
+ break;
310
+ case 'LineString':
311
+ case 'LinearRing':
312
+ const lineGeom = /** @type {import("../../geom").LineString} */ (
313
+ geometry
314
+ );
315
+ batchEntry = this.addFeatureEntryInLineStringBatch_(feature);
316
+ flatCoords = lineGeom.getFlatCoordinates();
317
+ verticesCount = flatCoords.length / 2;
318
+ this.lineStringBatch.verticesCount += verticesCount;
319
+ this.lineStringBatch.geometriesCount++;
320
+ batchEntry.flatCoordss.push(flatCoords);
321
+ batchEntry.verticesCount += verticesCount;
322
+ break;
323
+ default:
324
+ // pass
325
+ }
326
+ }
327
+
328
+ /**
329
+ * @param {import("../../Feature").default} feature Feature
330
+ */
331
+ changeFeature(feature) {
332
+ this.clearFeatureEntryInPointBatch_(feature);
333
+ this.clearFeatureEntryInPolygonBatch_(feature);
334
+ this.clearFeatureEntryInLineStringBatch_(feature);
335
+ const geometry = feature.getGeometry();
336
+ if (!geometry) {
337
+ return;
338
+ }
339
+ this.addGeometry_(geometry, feature);
340
+ }
341
+
342
+ /**
343
+ * @param {import("../../Feature").default} feature Feature
344
+ */
345
+ removeFeature(feature) {
346
+ this.clearFeatureEntryInPointBatch_(feature);
347
+ this.clearFeatureEntryInPolygonBatch_(feature);
348
+ this.clearFeatureEntryInLineStringBatch_(feature);
349
+ }
350
+
351
+ clear() {
352
+ this.polygonBatch.entries = {};
353
+ this.polygonBatch.geometriesCount = 0;
354
+ this.polygonBatch.verticesCount = 0;
355
+ this.polygonBatch.ringsCount = 0;
356
+ this.lineStringBatch.entries = {};
357
+ this.lineStringBatch.geometriesCount = 0;
358
+ this.lineStringBatch.verticesCount = 0;
359
+ this.pointBatch.entries = {};
360
+ this.pointBatch.geometriesCount = 0;
361
+ }
362
+ }
363
+
364
+ export default MixedGeometryBatch;