@mapwhit/tilerenderer 1.3.0 → 1.4.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.
Files changed (40) hide show
  1. package/build/min/package.json +1 -1
  2. package/package.json +1 -1
  3. package/src/data/array_types.js +115 -64
  4. package/src/data/bucket/circle_bucket.js +42 -5
  5. package/src/data/bucket/fill_bucket.js +31 -13
  6. package/src/data/bucket/fill_extrusion_bucket.js +8 -6
  7. package/src/data/bucket/line_bucket.js +38 -14
  8. package/src/data/bucket/symbol_attributes.js +13 -5
  9. package/src/data/bucket/symbol_bucket.js +87 -33
  10. package/src/data/bucket/symbol_collision_buffers.js +1 -1
  11. package/src/data/bucket.js +3 -1
  12. package/src/data/feature_index.js +24 -11
  13. package/src/data/segment.js +15 -7
  14. package/src/render/draw_circle.js +45 -4
  15. package/src/render/draw_symbol.js +190 -22
  16. package/src/render/painter.js +1 -1
  17. package/src/source/geojson_source.js +118 -21
  18. package/src/source/geojson_source_diff.js +148 -0
  19. package/src/source/geojson_tiler.js +89 -0
  20. package/src/source/source.js +16 -5
  21. package/src/source/source_cache.js +6 -6
  22. package/src/source/source_state.js +4 -2
  23. package/src/source/tile.js +5 -3
  24. package/src/source/vector_tile_source.js +2 -0
  25. package/src/source/worker_tile.js +4 -2
  26. package/src/style/pauseable_placement.js +39 -7
  27. package/src/style/style.js +17 -12
  28. package/src/style/style_layer/circle_style_layer_properties.js +8 -1
  29. package/src/style/style_layer/fill_style_layer_properties.js +8 -1
  30. package/src/style/style_layer/line_style_layer_properties.js +4 -0
  31. package/src/style/style_layer/symbol_style_layer_properties.js +17 -2
  32. package/src/style-spec/reference/v8.json +161 -4
  33. package/src/symbol/one_em.js +4 -0
  34. package/src/symbol/placement.js +406 -173
  35. package/src/symbol/projection.js +3 -3
  36. package/src/symbol/quads.js +1 -6
  37. package/src/symbol/shaping.js +16 -27
  38. package/src/symbol/symbol_layout.js +243 -81
  39. package/src/util/vectortile_to_geojson.js +3 -4
  40. package/src/source/geojson_worker_source.js +0 -97
@@ -1,4 +1,4 @@
1
1
  {
2
- "version": "1.3.0",
2
+ "version": "1.4.0",
3
3
  "type": "module"
4
4
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@mapwhit/tilerenderer",
3
3
  "description": "A WebGL interactive maps library",
4
- "version": "1.3.0",
4
+ "version": "1.4.0",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": "./src/index.js",
@@ -406,32 +406,40 @@ StructArrayLayout2i2i2i12.prototype.bytesPerElement = 12;
406
406
  /**
407
407
  * Implementation of the StructArray layout:
408
408
  * [0]: Uint8[2]
409
+ * [4]: Float32[2]
409
410
  *
410
411
  * @private
411
412
  */
412
- export class StructArrayLayout2ub4 extends StructArray {
413
+ export class StructArrayLayout2ub2f12 extends StructArray {
413
414
  _refreshViews() {
414
415
  this.uint8 = new Uint8Array(this.arrayBuffer);
416
+ this.float32 = new Float32Array(this.arrayBuffer);
415
417
  }
416
418
 
417
- emplaceBack(v0, v1) {
419
+ emplaceBack(v0, v1, v2, v3) {
418
420
  const i = this.length;
419
421
  this.resize(i + 1);
420
- const o1 = i * 4;
422
+ const o1 = i * 12;
423
+ const o4 = i * 3;
421
424
  this.uint8[o1 + 0] = v0;
422
425
  this.uint8[o1 + 1] = v1;
426
+ this.float32[o4 + 1] = v2;
427
+ this.float32[o4 + 2] = v3;
423
428
  return i;
424
429
  }
425
430
 
426
- emplace(i, v0, v1) {
427
- const o1 = i * 4;
431
+ emplace(i, v0, v1, v2, v3) {
432
+ const o1 = i * 12;
433
+ const o4 = i * 3;
428
434
  this.uint8[o1 + 0] = v0;
429
435
  this.uint8[o1 + 1] = v1;
436
+ this.float32[o4 + 1] = v2;
437
+ this.float32[o4 + 2] = v3;
430
438
  return i;
431
439
  }
432
440
  }
433
441
 
434
- StructArrayLayout2ub4.prototype.bytesPerElement = 4;
442
+ StructArrayLayout2ub2f12.prototype.bytesPerElement = 12;
435
443
 
436
444
  /**
437
445
  * Implementation of the StructArray layout:
@@ -441,10 +449,11 @@ StructArrayLayout2ub4.prototype.bytesPerElement = 4;
441
449
  * [20]: Uint16[3]
442
450
  * [28]: Float32[2]
443
451
  * [36]: Uint8[2]
452
+ * [40]: Uint32[1]
444
453
  *
445
454
  * @private
446
455
  */
447
- export class StructArrayLayout2i2ui3ul3ui2f2ub40 extends StructArray {
456
+ export class StructArrayLayout2i2ui3ul3ui2f2ub1ul44 extends StructArray {
448
457
  _refreshViews() {
449
458
  this.uint8 = new Uint8Array(this.arrayBuffer);
450
459
  this.int16 = new Int16Array(this.arrayBuffer);
@@ -453,12 +462,12 @@ export class StructArrayLayout2i2ui3ul3ui2f2ub40 extends StructArray {
453
462
  this.float32 = new Float32Array(this.arrayBuffer);
454
463
  }
455
464
 
456
- emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) {
465
+ emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) {
457
466
  const i = this.length;
458
467
  this.resize(i + 1);
459
- const o2 = i * 20;
460
- const o4 = i * 10;
461
- const o1 = i * 40;
468
+ const o2 = i * 22;
469
+ const o4 = i * 11;
470
+ const o1 = i * 44;
462
471
  this.int16[o2 + 0] = v0;
463
472
  this.int16[o2 + 1] = v1;
464
473
  this.uint16[o2 + 2] = v2;
@@ -473,13 +482,14 @@ export class StructArrayLayout2i2ui3ul3ui2f2ub40 extends StructArray {
473
482
  this.float32[o4 + 8] = v11;
474
483
  this.uint8[o1 + 36] = v12;
475
484
  this.uint8[o1 + 37] = v13;
485
+ this.uint32[o4 + 10] = v14;
476
486
  return i;
477
487
  }
478
488
 
479
- emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) {
480
- const o2 = i * 20;
481
- const o4 = i * 10;
482
- const o1 = i * 40;
489
+ emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) {
490
+ const o2 = i * 22;
491
+ const o4 = i * 11;
492
+ const o1 = i * 44;
483
493
  this.int16[o2 + 0] = v0;
484
494
  this.int16[o2 + 1] = v1;
485
495
  this.uint16[o2 + 2] = v2;
@@ -494,39 +504,42 @@ export class StructArrayLayout2i2ui3ul3ui2f2ub40 extends StructArray {
494
504
  this.float32[o4 + 8] = v11;
495
505
  this.uint8[o1 + 36] = v12;
496
506
  this.uint8[o1 + 37] = v13;
507
+ this.uint32[o4 + 10] = v14;
497
508
  return i;
498
509
  }
499
510
  }
500
511
 
501
- StructArrayLayout2i2ui3ul3ui2f2ub40.prototype.bytesPerElement = 40;
512
+ StructArrayLayout2i2ui3ul3ui2f2ub1ul44.prototype.bytesPerElement = 44;
502
513
 
503
514
  /**
504
515
  * Implementation of the StructArray layout:
505
- * [0]: Int16[4]
506
- * [8]: Uint16[9]
507
- * [28]: Uint32[1]
516
+ * [0]: Int16[6]
517
+ * [12]: Uint16[9]
518
+ * [32]: Uint32[1]
519
+ * [36]: Float32[2]
508
520
  *
509
521
  * @private
510
522
  */
511
- export class StructArrayLayout4i9ui1ul32 extends StructArray {
523
+ export class StructArrayLayout6i9ui1ul2f44 extends StructArray {
512
524
  _refreshViews() {
513
525
  this.uint8 = new Uint8Array(this.arrayBuffer);
514
526
  this.int16 = new Int16Array(this.arrayBuffer);
515
527
  this.uint16 = new Uint16Array(this.arrayBuffer);
516
528
  this.uint32 = new Uint32Array(this.arrayBuffer);
529
+ this.float32 = new Float32Array(this.arrayBuffer);
517
530
  }
518
531
 
519
- emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) {
532
+ emplaceBack(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) {
520
533
  const i = this.length;
521
534
  this.resize(i + 1);
522
- const o2 = i * 16;
523
- const o4 = i * 8;
535
+ const o2 = i * 22;
536
+ const o4 = i * 11;
524
537
  this.int16[o2 + 0] = v0;
525
538
  this.int16[o2 + 1] = v1;
526
539
  this.int16[o2 + 2] = v2;
527
540
  this.int16[o2 + 3] = v3;
528
- this.uint16[o2 + 4] = v4;
529
- this.uint16[o2 + 5] = v5;
541
+ this.int16[o2 + 4] = v4;
542
+ this.int16[o2 + 5] = v5;
530
543
  this.uint16[o2 + 6] = v6;
531
544
  this.uint16[o2 + 7] = v7;
532
545
  this.uint16[o2 + 8] = v8;
@@ -534,19 +547,23 @@ export class StructArrayLayout4i9ui1ul32 extends StructArray {
534
547
  this.uint16[o2 + 10] = v10;
535
548
  this.uint16[o2 + 11] = v11;
536
549
  this.uint16[o2 + 12] = v12;
537
- this.uint32[o4 + 7] = v13;
550
+ this.uint16[o2 + 13] = v13;
551
+ this.uint16[o2 + 14] = v14;
552
+ this.uint32[o4 + 8] = v15;
553
+ this.float32[o4 + 9] = v16;
554
+ this.float32[o4 + 10] = v17;
538
555
  return i;
539
556
  }
540
557
 
541
- emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) {
542
- const o2 = i * 16;
543
- const o4 = i * 8;
558
+ emplace(i, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) {
559
+ const o2 = i * 22;
560
+ const o4 = i * 11;
544
561
  this.int16[o2 + 0] = v0;
545
562
  this.int16[o2 + 1] = v1;
546
563
  this.int16[o2 + 2] = v2;
547
564
  this.int16[o2 + 3] = v3;
548
- this.uint16[o2 + 4] = v4;
549
- this.uint16[o2 + 5] = v5;
565
+ this.int16[o2 + 4] = v4;
566
+ this.int16[o2 + 5] = v5;
550
567
  this.uint16[o2 + 6] = v6;
551
568
  this.uint16[o2 + 7] = v7;
552
569
  this.uint16[o2 + 8] = v8;
@@ -554,12 +571,16 @@ export class StructArrayLayout4i9ui1ul32 extends StructArray {
554
571
  this.uint16[o2 + 10] = v10;
555
572
  this.uint16[o2 + 11] = v11;
556
573
  this.uint16[o2 + 12] = v12;
557
- this.uint32[o4 + 7] = v13;
574
+ this.uint16[o2 + 13] = v13;
575
+ this.uint16[o2 + 14] = v14;
576
+ this.uint32[o4 + 8] = v15;
577
+ this.float32[o4 + 9] = v16;
578
+ this.float32[o4 + 10] = v17;
558
579
  return i;
559
580
  }
560
581
  }
561
582
 
562
- StructArrayLayout4i9ui1ul32.prototype.bytesPerElement = 32;
583
+ StructArrayLayout6i9ui1ul2f44.prototype.bytesPerElement = 44;
563
584
 
564
585
  /**
565
586
  * Implementation of the StructArray layout:
@@ -992,14 +1013,20 @@ export class PlacedSymbolStruct extends Struct {
992
1013
  set hidden(x) {
993
1014
  this._structArray.uint8[this._pos1 + 37] = x;
994
1015
  }
1016
+ get crossTileID() {
1017
+ return this._structArray.uint32[this._pos4 + 10];
1018
+ }
1019
+ set crossTileID(x) {
1020
+ this._structArray.uint32[this._pos4 + 10] = x;
1021
+ }
995
1022
  }
996
1023
 
997
- PlacedSymbolStruct.prototype.size = 40;
1024
+ PlacedSymbolStruct.prototype.size = 44;
998
1025
 
999
1026
  /**
1000
1027
  * @private
1001
1028
  */
1002
- export class PlacedSymbolArray extends StructArrayLayout2i2ui3ul3ui2f2ub40 {
1029
+ export class PlacedSymbolArray extends StructArrayLayout2i2ui3ul3ui2f2ub1ul44 {
1003
1030
  /**
1004
1031
  * Return the PlacedSymbolStruct at the given location in the array.
1005
1032
  * @param {number} index The index of the element.
@@ -1023,86 +1050,110 @@ export class SymbolInstanceStruct extends Struct {
1023
1050
  set anchorY(x) {
1024
1051
  this._structArray.int16[this._pos2 + 1] = x;
1025
1052
  }
1026
- get horizontalPlacedTextSymbolIndex() {
1053
+ get rightJustifiedTextSymbolIndex() {
1027
1054
  return this._structArray.int16[this._pos2 + 2];
1028
1055
  }
1029
- set horizontalPlacedTextSymbolIndex(x) {
1056
+ set rightJustifiedTextSymbolIndex(x) {
1030
1057
  this._structArray.int16[this._pos2 + 2] = x;
1031
1058
  }
1032
- get verticalPlacedTextSymbolIndex() {
1059
+ get centerJustifiedTextSymbolIndex() {
1033
1060
  return this._structArray.int16[this._pos2 + 3];
1034
1061
  }
1035
- set verticalPlacedTextSymbolIndex(x) {
1062
+ set centerJustifiedTextSymbolIndex(x) {
1036
1063
  this._structArray.int16[this._pos2 + 3] = x;
1037
1064
  }
1065
+ get leftJustifiedTextSymbolIndex() {
1066
+ return this._structArray.int16[this._pos2 + 4];
1067
+ }
1068
+ set leftJustifiedTextSymbolIndex(x) {
1069
+ this._structArray.int16[this._pos2 + 4] = x;
1070
+ }
1071
+ get verticalPlacedTextSymbolIndex() {
1072
+ return this._structArray.int16[this._pos2 + 5];
1073
+ }
1074
+ set verticalPlacedTextSymbolIndex(x) {
1075
+ this._structArray.int16[this._pos2 + 5] = x;
1076
+ }
1038
1077
  get key() {
1039
- return this._structArray.uint16[this._pos2 + 4];
1078
+ return this._structArray.uint16[this._pos2 + 6];
1040
1079
  }
1041
1080
  set key(x) {
1042
- this._structArray.uint16[this._pos2 + 4] = x;
1081
+ this._structArray.uint16[this._pos2 + 6] = x;
1043
1082
  }
1044
1083
  get textBoxStartIndex() {
1045
- return this._structArray.uint16[this._pos2 + 5];
1084
+ return this._structArray.uint16[this._pos2 + 7];
1046
1085
  }
1047
1086
  set textBoxStartIndex(x) {
1048
- this._structArray.uint16[this._pos2 + 5] = x;
1087
+ this._structArray.uint16[this._pos2 + 7] = x;
1049
1088
  }
1050
1089
  get textBoxEndIndex() {
1051
- return this._structArray.uint16[this._pos2 + 6];
1090
+ return this._structArray.uint16[this._pos2 + 8];
1052
1091
  }
1053
1092
  set textBoxEndIndex(x) {
1054
- this._structArray.uint16[this._pos2 + 6] = x;
1093
+ this._structArray.uint16[this._pos2 + 8] = x;
1055
1094
  }
1056
1095
  get iconBoxStartIndex() {
1057
- return this._structArray.uint16[this._pos2 + 7];
1096
+ return this._structArray.uint16[this._pos2 + 9];
1058
1097
  }
1059
1098
  set iconBoxStartIndex(x) {
1060
- this._structArray.uint16[this._pos2 + 7] = x;
1099
+ this._structArray.uint16[this._pos2 + 9] = x;
1061
1100
  }
1062
1101
  get iconBoxEndIndex() {
1063
- return this._structArray.uint16[this._pos2 + 8];
1102
+ return this._structArray.uint16[this._pos2 + 10];
1064
1103
  }
1065
1104
  set iconBoxEndIndex(x) {
1066
- this._structArray.uint16[this._pos2 + 8] = x;
1105
+ this._structArray.uint16[this._pos2 + 10] = x;
1067
1106
  }
1068
1107
  get featureIndex() {
1069
- return this._structArray.uint16[this._pos2 + 9];
1108
+ return this._structArray.uint16[this._pos2 + 11];
1070
1109
  }
1071
1110
  set featureIndex(x) {
1072
- this._structArray.uint16[this._pos2 + 9] = x;
1111
+ this._structArray.uint16[this._pos2 + 11] = x;
1073
1112
  }
1074
- get numGlyphVertices() {
1075
- return this._structArray.uint16[this._pos2 + 10];
1113
+ get numHorizontalGlyphVertices() {
1114
+ return this._structArray.uint16[this._pos2 + 12];
1076
1115
  }
1077
- set numGlyphVertices(x) {
1078
- this._structArray.uint16[this._pos2 + 10] = x;
1116
+ set numHorizontalGlyphVertices(x) {
1117
+ this._structArray.uint16[this._pos2 + 12] = x;
1079
1118
  }
1080
1119
  get numVerticalGlyphVertices() {
1081
- return this._structArray.uint16[this._pos2 + 11];
1120
+ return this._structArray.uint16[this._pos2 + 13];
1082
1121
  }
1083
1122
  set numVerticalGlyphVertices(x) {
1084
- this._structArray.uint16[this._pos2 + 11] = x;
1123
+ this._structArray.uint16[this._pos2 + 13] = x;
1085
1124
  }
1086
1125
  get numIconVertices() {
1087
- return this._structArray.uint16[this._pos2 + 12];
1126
+ return this._structArray.uint16[this._pos2 + 14];
1088
1127
  }
1089
1128
  set numIconVertices(x) {
1090
- this._structArray.uint16[this._pos2 + 12] = x;
1129
+ this._structArray.uint16[this._pos2 + 14] = x;
1091
1130
  }
1092
1131
  get crossTileID() {
1093
- return this._structArray.uint32[this._pos4 + 7];
1132
+ return this._structArray.uint32[this._pos4 + 8];
1094
1133
  }
1095
1134
  set crossTileID(x) {
1096
- this._structArray.uint32[this._pos4 + 7] = x;
1135
+ this._structArray.uint32[this._pos4 + 8] = x;
1136
+ }
1137
+ get textBoxScale() {
1138
+ return this._structArray.float32[this._pos4 + 9];
1139
+ }
1140
+ set textBoxScale(x) {
1141
+ this._structArray.float32[this._pos4 + 9] = x;
1142
+ }
1143
+ get radialTextOffset() {
1144
+ return this._structArray.float32[this._pos4 + 10];
1145
+ }
1146
+ set radialTextOffset(x) {
1147
+ this._structArray.float32[this._pos4 + 10] = x;
1097
1148
  }
1098
1149
  }
1099
1150
 
1100
- SymbolInstanceStruct.prototype.size = 32;
1151
+ SymbolInstanceStruct.prototype.size = 44;
1101
1152
 
1102
1153
  /**
1103
1154
  * @private
1104
1155
  */
1105
- export class SymbolInstanceArray extends StructArrayLayout4i9ui1ul32 {
1156
+ export class SymbolInstanceArray extends StructArrayLayout6i9ui1ul2f44 {
1106
1157
  /**
1107
1158
  * Return the SymbolInstanceStruct at the given location in the array.
1108
1159
  * @param {number} index The index of the element.
@@ -1238,7 +1289,7 @@ export {
1238
1289
  StructArrayLayout1ul4 as SymbolOpacityArray,
1239
1290
  StructArrayLayout2i2i2i12 as CollisionBoxLayoutArray,
1240
1291
  StructArrayLayout2i2i2i12 as CollisionCircleLayoutArray,
1241
- StructArrayLayout2ub4 as CollisionVertexArray,
1292
+ StructArrayLayout2ub2f12 as CollisionVertexArray,
1242
1293
  StructArrayLayout3ui6 as TriangleIndexArray,
1243
1294
  StructArrayLayout2ui4 as LineIndexArray,
1244
1295
  StructArrayLayout1ui2 as LineStripIndexArray
@@ -32,16 +32,53 @@ class CircleBucket {
32
32
  this.indexArray = new TriangleIndexArray();
33
33
  this.segments = new SegmentVector();
34
34
  this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, options.layers, options.zoom);
35
+ this.stateDependentLayerIds = this.layers.filter(l => l.isStateDependent()).map(l => l.id);
35
36
  }
36
37
 
37
38
  populate(features, options) {
38
- for (const { feature, index, sourceLayerIndex } of features) {
39
- if (this.layers[0]._featureFilter(new EvaluationParameters(this.zoom), feature)) {
39
+ const styleLayer = this.layers[0];
40
+ const bucketFeatures = [];
41
+ let circleSortKey = null;
42
+
43
+ // Heatmap layers are handled in this bucket and have no evaluated properties, so we check our access
44
+ if (styleLayer.type === 'circle') {
45
+ circleSortKey = styleLayer._layout.get('circle-sort-key');
46
+ }
47
+
48
+ for (const { feature, id, index, sourceLayerIndex } of features) {
49
+ if (styleLayer._featureFilter(new EvaluationParameters(this.zoom), feature)) {
40
50
  const geometry = loadGeometry(feature);
41
- this.addFeature(feature, geometry, index);
42
- options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
51
+ const sortKey = circleSortKey ? circleSortKey.evaluate(feature, {}) : undefined;
52
+
53
+ const bucketFeature = {
54
+ id,
55
+ properties: feature.properties,
56
+ type: feature.type,
57
+ sourceLayerIndex,
58
+ index,
59
+ geometry,
60
+ patterns: {},
61
+ sortKey
62
+ };
63
+
64
+ bucketFeatures.push(bucketFeature);
43
65
  }
44
66
  }
67
+
68
+ if (circleSortKey) {
69
+ bucketFeatures.sort((a, b) => {
70
+ // a.sortKey is always a number when in use
71
+ return a.sortKey - b.sortKey;
72
+ });
73
+ }
74
+
75
+ for (const bucketFeature of bucketFeatures) {
76
+ const { geometry, index, sourceLayerIndex } = bucketFeature;
77
+ const feature = features[index].feature;
78
+
79
+ this.addFeature(bucketFeature, geometry, index);
80
+ options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
81
+ }
45
82
  }
46
83
 
47
84
  update(states, vtLayer, imagePositions) {
@@ -100,7 +137,7 @@ class CircleBucket {
100
137
  // │ 0 1 │
101
138
  // └─────────┘
102
139
 
103
- const segment = this.segments.prepareSegment(4, this.layoutVertexArray, this.indexArray);
140
+ const segment = this.segments.prepareSegment(4, this.layoutVertexArray, this.indexArray, feature.sortKey);
104
141
  const index = segment.vertexLength;
105
142
 
106
143
  addCircleVertex(this.layoutVertexArray, x, y, -1, -1);
@@ -20,6 +20,7 @@ class FillBucket {
20
20
  this.layers = options.layers;
21
21
  this.index = options.index;
22
22
  this.hasPattern = false;
23
+ this.features = [];
23
24
 
24
25
  this.layoutVertexArray = new FillLayoutArray();
25
26
  this.indexArray = new TriangleIndexArray();
@@ -27,38 +28,56 @@ class FillBucket {
27
28
  this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, options.layers, options.zoom);
28
29
  this.segments = new SegmentVector();
29
30
  this.segments2 = new SegmentVector();
31
+ this.stateDependentLayerIds = this.layers.filter(l => l.isStateDependent()).map(l => l.id);
30
32
  }
31
33
 
32
34
  populate(features, options) {
33
- this.features = [];
34
35
  this.hasPattern = hasPattern('fill', this.layers, options);
36
+ const fillSortKey = this.layers[0]._layout.get('fill-sort-key');
37
+ const bucketFeatures = [];
35
38
 
36
- for (const { feature, index, sourceLayerIndex } of features) {
39
+ for (const { feature, id, index, sourceLayerIndex } of features) {
37
40
  if (!this.layers[0]._featureFilter(new EvaluationParameters(this.zoom), feature)) {
38
41
  continue;
39
42
  }
40
43
 
41
44
  const geometry = loadGeometry(feature);
45
+ const sortKey = fillSortKey ? fillSortKey.evaluate(feature, {}) : undefined;
42
46
 
43
- const patternFeature = {
47
+ const bucketFeature = {
48
+ id,
49
+ properties: feature.properties,
50
+ type: feature.type,
44
51
  sourceLayerIndex,
45
52
  index,
46
53
  geometry,
47
- properties: feature.properties,
48
- type: feature.type,
49
- patterns: {}
54
+ patterns: {},
55
+ sortKey
50
56
  };
51
57
 
52
- if (typeof feature.id !== 'undefined') {
53
- patternFeature.id = feature.id;
54
- }
58
+ bucketFeatures.push(bucketFeature);
59
+ }
60
+
61
+ if (fillSortKey) {
62
+ bucketFeatures.sort((a, b) => {
63
+ // a.sortKey is always a number when in use
64
+ return a.sortKey - b.sortKey;
65
+ });
66
+ }
67
+
68
+ for (const bucketFeature of bucketFeatures) {
69
+ const { geometry, index, sourceLayerIndex } = bucketFeature;
55
70
 
56
71
  if (this.hasPattern) {
57
- this.features.push(addPatternDependencies('fill', this.layers, patternFeature, { zoom: this.zoom }, options));
72
+ const patternFeature = addPatternDependencies('fill', this.layers, bucketFeature, { zoom: this.zoom }, options);
73
+ // pattern features are added only once the pattern is loaded into the image atlas
74
+ // so are stored during populate until later updated with positions by tile worker in addFeatures
75
+ this.features.push(patternFeature);
58
76
  } else {
59
- this.addFeature(patternFeature, geometry, index, {});
77
+ this.addFeature(bucketFeature, geometry, index, {});
60
78
  }
61
79
 
80
+ const feature = features[index].feature;
62
81
  options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
63
82
  }
64
83
  }
@@ -74,8 +93,7 @@ class FillBucket {
74
93
 
75
94
  addFeatures(options, imagePositions) {
76
95
  for (const feature of this.features) {
77
- const { geometry } = feature;
78
- this.addFeature(feature, geometry, feature.index, imagePositions);
96
+ this.addFeature(feature, feature.geometry, feature.index, imagePositions);
79
97
  }
80
98
  }
81
99
 
@@ -45,20 +45,22 @@ export default class FillExtrusionBucket {
45
45
  this.indexArray = new TriangleIndexArray();
46
46
  this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, options.layers, options.zoom);
47
47
  this.segments = new SegmentVector();
48
+ this.stateDependentLayerIds = this.layers.filter(l => l.isStateDependent()).map(l => l.id);
48
49
  }
49
50
 
50
51
  populate(features, options) {
51
52
  this.features = [];
52
53
  this.hasPattern = hasPattern('fill-extrusion', this.layers, options);
53
54
 
54
- for (const { feature, index, sourceLayerIndex } of features) {
55
+ for (const { feature, id, index, sourceLayerIndex } of features) {
55
56
  if (!this.layers[0]._featureFilter(new EvaluationParameters(this.zoom), feature)) {
56
57
  continue;
57
58
  }
58
59
 
59
60
  const geometry = loadGeometry(feature);
60
61
 
61
- const patternFeature = {
62
+ const bucketFeature = {
63
+ id,
62
64
  sourceLayerIndex,
63
65
  index,
64
66
  geometry,
@@ -67,16 +69,16 @@ export default class FillExtrusionBucket {
67
69
  patterns: {}
68
70
  };
69
71
 
70
- if (typeof feature.id !== 'undefined') {
71
- patternFeature.id = feature.id;
72
+ if (typeof feature.id !== 'undefined' && typeof bucketFeature.id === 'undefined') {
73
+ bucketFeature.id = feature.id;
72
74
  }
73
75
 
74
76
  if (this.hasPattern) {
75
77
  this.features.push(
76
- addPatternDependencies('fill-extrusion', this.layers, patternFeature, { zoom: this.zoom }, options)
78
+ addPatternDependencies('fill-extrusion', this.layers, bucketFeature, { zoom: this.zoom }, options)
77
79
  );
78
80
  } else {
79
- this.addFeature(patternFeature, geometry, index, {});
81
+ this.addFeature(bucketFeature, geometry, index, {});
80
82
  }
81
83
 
82
84
  options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index, true);
@@ -71,45 +71,70 @@ export default class LineBucket {
71
71
  this.overscaling = overscaling;
72
72
  this.layers = layers;
73
73
  this.index = index;
74
- this.features = [];
75
74
  this.hasPattern = false;
75
+ this.features = [];
76
76
 
77
77
  this.layoutVertexArray = new LineLayoutArray();
78
78
  this.indexArray = new TriangleIndexArray();
79
79
  this.programConfigurations = new ProgramConfigurationSet(layoutAttributes, layers, zoom);
80
80
  this.segments = new SegmentVector();
81
+
82
+ this.stateDependentLayerIds = this.layers.filter(l => l.isStateDependent()).map(l => l.id);
81
83
  }
82
84
 
83
85
  populate(features, options) {
84
- this.features = [];
85
86
  this.hasPattern = hasPattern('line', this.layers, options);
87
+ const lineSortKey = this.layers[0]._layout.get('line-sort-key');
88
+ const bucketFeatures = [];
86
89
 
87
- for (const { feature, index, sourceLayerIndex } of features) {
90
+ for (const { feature, id, index, sourceLayerIndex } of features) {
88
91
  if (!this.layers[0]._featureFilter(new EvaluationParameters(this.zoom), feature)) {
89
92
  continue;
90
93
  }
91
94
 
92
95
  const geometry = loadGeometry(feature);
96
+ const sortKey = lineSortKey ? lineSortKey.evaluate(feature, {}) : undefined;
93
97
 
94
- const patternFeature = {
98
+ const bucketFeature = {
99
+ id,
100
+ properties: feature.properties,
101
+ type: feature.type,
95
102
  sourceLayerIndex,
96
103
  index,
97
104
  geometry,
98
- properties: feature.properties,
99
- type: feature.type,
100
- patterns: {}
105
+ patterns: {},
106
+ sortKey
101
107
  };
102
108
 
103
- if (typeof feature.id !== 'undefined') {
104
- patternFeature.id = feature.id;
105
- }
109
+ bucketFeatures.push(bucketFeature);
110
+ }
111
+
112
+ if (lineSortKey) {
113
+ bucketFeatures.sort((a, b) => {
114
+ // a.sortKey is always a number when in use
115
+ return a.sortKey - b.sortKey;
116
+ });
117
+ }
118
+
119
+ for (const bucketFeature of bucketFeatures) {
120
+ const { geometry, index, sourceLayerIndex } = bucketFeature;
106
121
 
107
122
  if (this.hasPattern) {
108
- this.features.push(addPatternDependencies('line', this.layers, patternFeature, { zoom: this.zoom }, options));
123
+ const patternBucketFeature = addPatternDependencies(
124
+ 'line',
125
+ this.layers,
126
+ bucketFeature,
127
+ { zoom: this.zoom },
128
+ options
129
+ );
130
+ // pattern features are added only once the pattern is loaded into the image atlas
131
+ // so are stored during populate until later updated with positions by tile worker in addFeatures
132
+ this.features.push(patternBucketFeature);
109
133
  } else {
110
- this.addFeature(patternFeature, geometry, index, {});
134
+ this.addFeature(bucketFeature, geometry, index, {});
111
135
  }
112
136
 
137
+ const feature = features[index].feature;
113
138
  options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
114
139
  }
115
140
  }
@@ -125,8 +150,7 @@ export default class LineBucket {
125
150
 
126
151
  addFeatures(options, imagePositions) {
127
152
  for (const feature of this.features) {
128
- const { geometry } = feature;
129
- this.addFeature(feature, geometry, feature.index, imagePositions);
153
+ this.addFeature(feature, feature.geometry, feature.index, imagePositions);
130
154
  }
131
155
  }
132
156