@mapwhit/tilerenderer 1.1.1 → 1.2.1

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 (45) hide show
  1. package/build/min/package.json +1 -1
  2. package/package.json +5 -5
  3. package/src/data/bucket/circle_bucket.js +3 -8
  4. package/src/data/bucket/fill_bucket.js +4 -17
  5. package/src/data/bucket/fill_extrusion_bucket.js +4 -15
  6. package/src/data/bucket/line_bucket.js +4 -17
  7. package/src/data/bucket/pattern_bucket_features.js +4 -4
  8. package/src/data/bucket/symbol_bucket.js +4 -8
  9. package/src/data/feature_index.js +1 -1
  10. package/src/source/geojson_source.js +4 -3
  11. package/src/source/geojson_worker_source.js +26 -10
  12. package/src/source/load_tilejson.js +18 -6
  13. package/src/source/raster_tile_source.js +4 -5
  14. package/src/source/tile.js +3 -0
  15. package/src/source/vector_tile_source.js +4 -6
  16. package/src/source/vector_tile_worker_source.js +6 -26
  17. package/src/source/worker_tile.js +67 -53
  18. package/src/style/create_style_layer.js +2 -2
  19. package/src/style/evaluation_parameters.js +0 -2
  20. package/src/style/properties.js +24 -15
  21. package/src/style/style.js +18 -8
  22. package/src/style/style_layer/background_style_layer.js +2 -2
  23. package/src/style/style_layer/circle_style_layer.js +3 -3
  24. package/src/style/style_layer/fill_extrusion_style_layer.js +3 -3
  25. package/src/style/style_layer/fill_style_layer.js +3 -3
  26. package/src/style/style_layer/heatmap_style_layer.js +3 -3
  27. package/src/style/style_layer/hillshade_style_layer.js +3 -3
  28. package/src/style/style_layer/line_style_layer.js +3 -3
  29. package/src/style/style_layer/raster_style_layer.js +2 -2
  30. package/src/style/style_layer/symbol_style_layer.js +2 -2
  31. package/src/style/style_layer.js +28 -7
  32. package/src/style-spec/feature_filter/index.js +7 -5
  33. package/src/style-spec/reference/v8.json +68 -9
  34. package/src/style-spec/visibility.js +37 -0
  35. package/src/symbol/collision_index.js +2 -2
  36. package/src/symbol/symbol_layout.js +1 -1
  37. package/src/ui/map.js +10 -3
  38. package/src/util/classify_rings.js +1 -1
  39. package/src/util/group_layers.js +1 -1
  40. package/src/util/object.js +0 -45
  41. package/src/util/util.js +0 -55
  42. package/build/min/src/shaders/.dir +0 -0
  43. package/src/util/async.js +0 -29
  44. package/src/util/find_pole_of_inaccessibility.js +0 -144
  45. package/src/util/intersection_tests.js +0 -245
@@ -393,6 +393,11 @@
393
393
  "type": "boolean",
394
394
  "default": false,
395
395
  "doc": "Whether to calculate line distance metrics. This is required for line layers that specify `line-gradient` values."
396
+ },
397
+ "generateId": {
398
+ "type": "boolean",
399
+ "default": false,
400
+ "doc": "Whether to generate ids for the geojson features. When enabled, the `feature.id` property will be auto assigned based on it's index in the `features` array, over-writing any previous values."
396
401
  }
397
402
  },
398
403
  "source_video": {
@@ -635,7 +640,13 @@
635
640
  "macos": "0.1.0"
636
641
  }
637
642
  },
638
- "property-type": "constant"
643
+ "expression": {
644
+ "interpolated": false,
645
+ "parameters": [
646
+ "global-state"
647
+ ]
648
+ },
649
+ "property-type": "data-constant"
639
650
  }
640
651
  },
641
652
  "layout_fill": {
@@ -659,7 +670,13 @@
659
670
  "macos": "0.1.0"
660
671
  }
661
672
  },
662
- "property-type": "constant"
673
+ "expression": {
674
+ "interpolated": false,
675
+ "parameters": [
676
+ "global-state"
677
+ ]
678
+ },
679
+ "property-type": "data-constant"
663
680
  }
664
681
  },
665
682
  "layout_circle": {
@@ -683,7 +700,13 @@
683
700
  "macos": "0.1.0"
684
701
  }
685
702
  },
686
- "property-type": "constant"
703
+ "expression": {
704
+ "interpolated": false,
705
+ "parameters": [
706
+ "global-state"
707
+ ]
708
+ },
709
+ "property-type": "data-constant"
687
710
  }
688
711
  },
689
712
  "layout_heatmap": {
@@ -707,7 +730,13 @@
707
730
  "macos": "0.7.0"
708
731
  }
709
732
  },
710
- "property-type": "constant"
733
+ "expression": {
734
+ "interpolated": false,
735
+ "parameters": [
736
+ "global-state"
737
+ ]
738
+ },
739
+ "property-type": "data-constant"
711
740
  }
712
741
  },
713
742
  "layout_fill-extrusion": {
@@ -731,7 +760,13 @@
731
760
  "macos": "0.5.0"
732
761
  }
733
762
  },
734
- "property-type": "constant"
763
+ "expression": {
764
+ "interpolated": false,
765
+ "parameters": [
766
+ "global-state"
767
+ ]
768
+ },
769
+ "property-type": "data-constant"
735
770
  }
736
771
  },
737
772
  "layout_line": {
@@ -878,7 +913,13 @@
878
913
  },
879
914
  "data-driven styling": {}
880
915
  },
881
- "property-type": "constant"
916
+ "expression": {
917
+ "interpolated": false,
918
+ "parameters": [
919
+ "global-state"
920
+ ]
921
+ },
922
+ "property-type": "data-constant"
882
923
  }
883
924
  },
884
925
  "layout_symbol": {
@@ -2121,7 +2162,13 @@
2121
2162
  },
2122
2163
  "data-driven styling": {}
2123
2164
  },
2124
- "property-type": "constant"
2165
+ "expression": {
2166
+ "interpolated": false,
2167
+ "parameters": [
2168
+ "global-state"
2169
+ ]
2170
+ },
2171
+ "property-type": "data-constant"
2125
2172
  }
2126
2173
  },
2127
2174
  "layout_raster": {
@@ -2146,7 +2193,13 @@
2146
2193
  },
2147
2194
  "data-driven styling": {}
2148
2195
  },
2149
- "property-type": "constant"
2196
+ "expression": {
2197
+ "interpolated": false,
2198
+ "parameters": [
2199
+ "global-state"
2200
+ ]
2201
+ },
2202
+ "property-type": "data-constant"
2150
2203
  }
2151
2204
  },
2152
2205
  "layout_hillshade": {
@@ -2171,7 +2224,13 @@
2171
2224
  },
2172
2225
  "data-driven styling": {}
2173
2226
  },
2174
- "property-type": "constant"
2227
+ "expression": {
2228
+ "interpolated": false,
2229
+ "parameters": [
2230
+ "global-state"
2231
+ ]
2232
+ },
2233
+ "property-type": "data-constant"
2175
2234
  }
2176
2235
  },
2177
2236
  "filter": {
@@ -0,0 +1,37 @@
1
+ import { createExpression, findGlobalStateRefs } from '@mapwhit/style-expressions';
2
+
3
+ const visibilitySpec = {
4
+ type: 'enum',
5
+ values: ['visible', 'none'],
6
+ default: 'visible',
7
+ expression: {
8
+ parameters: ['global-state']
9
+ }
10
+ };
11
+
12
+ export default function createVisibility(visibility, globalState) {
13
+ const expression = {
14
+ setValue
15
+ };
16
+ setValue(visibility);
17
+ return expression;
18
+
19
+ function setValue(visibility) {
20
+ if (visibility === null || visibility === undefined || visibility === 'visible' || visibility === 'none') {
21
+ expression.evaluate = visibility === 'none' ? () => 'none' : () => 'visible';
22
+ addGlobalStateRefs(expression);
23
+ return;
24
+ }
25
+
26
+ const compiled = createExpression(visibility, visibilitySpec, globalState);
27
+ if (compiled.result === 'error') {
28
+ throw new Error(compiled.value.map(err => `${err.key}: ${err.message}`).join(', '));
29
+ }
30
+ expression.evaluate = () => compiled.value.evaluate({});
31
+ addGlobalStateRefs(expression, () => findGlobalStateRefs(compiled.value.expression));
32
+ }
33
+ }
34
+
35
+ function addGlobalStateRefs(visibility, getGlobalStateRefs = () => new Set()) {
36
+ visibility.getGlobalStateRefs = getGlobalStateRefs;
37
+ }
@@ -1,6 +1,6 @@
1
1
  import Point from '@mapbox/point-geometry';
2
+ import { polygonIntersectsPolygon } from '@mapwhit/geometry';
2
3
  import * as projection from '../symbol/projection.js';
3
- import * as intersectionTests from '../util/intersection_tests.js';
4
4
  import Grid from './grid_index.js';
5
5
 
6
6
  // When a symbol crosses the edge that causes it to be included in
@@ -293,7 +293,7 @@ class CollisionIndex {
293
293
  new Point(feature.x2, feature.y2),
294
294
  new Point(feature.x1, feature.y2)
295
295
  ];
296
- if (!intersectionTests.polygonIntersectsPolygon(query, bbox)) {
296
+ if (!polygonIntersectsPolygon(query, bbox)) {
297
297
  continue;
298
298
  }
299
299
 
@@ -1,9 +1,9 @@
1
+ import { findPoleOfInaccessibility } from '@mapwhit/geometry';
1
2
  import murmur3 from 'murmurhash-js';
2
3
  import SymbolBucket from '../data/bucket/symbol_bucket.js';
3
4
  import EXTENT from '../data/extent.js';
4
5
  import EvaluationParameters from '../style/evaluation_parameters.js';
5
6
  import classifyRings from '../util/classify_rings.js';
6
- import findPoleOfInaccessibility from '../util/find_pole_of_inaccessibility.js';
7
7
  import { allowsLetterSpacing, allowsVerticalWritingMode } from '../util/script_detection.js';
8
8
  import warn from '../util/warn.js';
9
9
  import Anchor from './anchor.js';
package/src/ui/map.js CHANGED
@@ -1069,11 +1069,17 @@ class Map extends Camera {
1069
1069
  *
1070
1070
  * @param {Object} [feature] Feature identifier. Feature objects returned from
1071
1071
  * {@link Map#queryRenderedFeatures} or event handlers can be used as feature identifiers.
1072
+ * @param {string} [feature.id] Unique id of the feature.
1072
1073
  * @param {string} [feature.source] The Id of the vector source or GeoJSON source for the feature.
1073
1074
  * @param {string} [feature.sourceLayer] (optional) *For vector tile sources, the sourceLayer is
1074
1075
  * required.*
1075
- * @param {string} [feature.id] Unique id of the feature.
1076
1076
  * @param {Object} state A set of key-value pairs. The values should be valid JSON types.
1077
+ *
1078
+ * This method requires the `feature.id` attribute on data sets. For GeoJSON sources without
1079
+ * feature ids, set the `generateIds` option in the `GeoJSONSourceSpecification` to auto-assign them. This
1080
+ * option assigns ids based on a feature's index in the source data. Changing the feature data using
1081
+ * `map.getSource('some id').setData(..)` resets the cache of feature states and requires the
1082
+ * caller re-apply the state as needed with the updated `id` values.
1077
1083
  */
1078
1084
  setFeatureState(feature, state) {
1079
1085
  this.style.setFeatureState(feature, state);
@@ -1320,8 +1326,7 @@ class Map extends Camera {
1320
1326
  now,
1321
1327
  fadeDuration: this._fadeDuration,
1322
1328
  zoomHistory: this.style.zoomHistory,
1323
- transition: this.style.getTransition(),
1324
- globalState: this.style.getGlobalState()
1329
+ transition: this.style.getTransition()
1325
1330
  });
1326
1331
 
1327
1332
  const factor = parameters.crossFadingFactor();
@@ -1383,6 +1388,8 @@ class Map extends Camera {
1383
1388
  // Style#_updateSources could have caused them to be set again.
1384
1389
  if (this._sourcesDirty || this._repaint || this._styleDirty || this._placementDirty) {
1385
1390
  this._rerender();
1391
+ } else if (!this.isMoving() && this.loaded()) {
1392
+ this.fire(new Event('idle'));
1386
1393
  }
1387
1394
 
1388
1395
  return this;
@@ -1,5 +1,5 @@
1
+ import { calculateSignedArea } from '@mapwhit/geometry';
1
2
  import quickselect from 'quickselect';
2
- import { calculateSignedArea } from './util.js';
3
3
 
4
4
  // classifies an array of rings into polygons with outer rings and holes
5
5
  export default function classifyRings(rings, maxRings) {
@@ -15,7 +15,7 @@ function groupBySource(layers) {
15
15
 
16
16
  // Iterate through each layer and group them by source, source-layer, and layout properties
17
17
  for (const layer of layers) {
18
- if (layer.visibility === 'none') {
18
+ if (layer.isHidden()) {
19
19
  continue;
20
20
  }
21
21
 
@@ -1,22 +1,3 @@
1
- /**
2
- * Given an object and a number of properties as strings, return version
3
- * of that object with only those properties.
4
- *
5
- * @param src the object
6
- * @param properties an array of property names chosen
7
- * to appear on the resulting object.
8
- * @returns object with limited properties.
9
- * @example
10
- * var foo = { name: 'Charlie', age: 10 };
11
- * var justName = pick(foo, ['name']);
12
- * // justName = { name: 'Charlie' }
13
- * @private
14
- */
15
- export function pick(src, properties) {
16
- const entries = properties.filter(p => p in src).map(p => [p, src[p]]);
17
- return Object.fromEntries(entries);
18
- }
19
-
20
1
  /**
21
2
  * Given an array of member function names as strings, replace all of them
22
3
  * with bound versions that will always refer to `context` as `this`. This
@@ -59,17 +40,6 @@ export function mapObject(input, iterator, context) {
59
40
  return Object.fromEntries(entries);
60
41
  }
61
42
 
62
- /**
63
- * Create an object by filtering out values of an existing object.
64
- *
65
- * @private
66
- */
67
- export function filterObject(input, iterator, context) {
68
- context ??= this;
69
- const entries = Object.entries(input).filter(([k, v]) => iterator.call(context, v, k, input));
70
- return Object.fromEntries(entries);
71
- }
72
-
73
43
  /**
74
44
  * Deeply compares two object literals.
75
45
  *
@@ -105,21 +75,6 @@ export function deepEqual(a, b) {
105
75
  return a === b;
106
76
  }
107
77
 
108
- /**
109
- * Deeply clones two objects.
110
- *
111
- * @private
112
- */
113
- export function clone(input) {
114
- if (Array.isArray(input)) {
115
- return input.map(clone);
116
- }
117
- if (typeof input === 'object' && input) {
118
- return mapObject(input, clone);
119
- }
120
- return input;
121
- }
122
-
123
78
  /**
124
79
  * Check if two arrays have at least one common element.
125
80
  *
package/src/util/util.js CHANGED
@@ -104,61 +104,6 @@ export function getCoordinatesCenter(coords) {
104
104
  return new Coordinate((minX + maxX) / 2, (minY + maxY) / 2, 0).zoomTo(zoom);
105
105
  }
106
106
 
107
- /**
108
- * Indicates if the provided Points are in a counter clockwise (true) or clockwise (false) order
109
- *
110
- * @private
111
- * @returns true for a counter clockwise set of points
112
- */
113
- // http://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/
114
- export function isCounterClockwise(a, b, c) {
115
- return (c.y - a.y) * (b.x - a.x) > (b.y - a.y) * (c.x - a.x);
116
- }
117
-
118
- /**
119
- * Returns the signed area for the polygon ring. Postive areas are exterior rings and
120
- * have a clockwise winding. Negative areas are interior rings and have a counter clockwise
121
- * ordering.
122
- *
123
- * @private
124
- * @param ring Exterior or interior ring
125
- */
126
- export function calculateSignedArea(ring) {
127
- let sum = 0;
128
- const len = ring.length;
129
- let p2 = ring[len - 1]; // last point
130
- for (const p1 of ring) {
131
- sum += (p2.x - p1.x) * (p1.y + p2.y);
132
- p2 = p1;
133
- }
134
- return sum;
135
- }
136
-
137
- /**
138
- * Detects closed polygons, first + last point are equal
139
- *
140
- * @private
141
- * @param points array of points
142
- * @return true if the points are a closed polygon
143
- */
144
- export function isClosedPolygon(points) {
145
- // If it is 2 points that are the same then it is a point
146
- // If it is 3 points with start and end the same then it is a line
147
- if (points.length < 4) {
148
- return false;
149
- }
150
-
151
- const p1 = points[0];
152
- const p2 = points[points.length - 1];
153
-
154
- if (Math.abs(p1.x - p2.x) > 0 || Math.abs(p1.y - p2.y) > 0) {
155
- return false;
156
- }
157
-
158
- // polygon simplification can produce polygons with zero area and more than 3 points
159
- return Math.abs(calculateSignedArea(points)) > 0.01;
160
- }
161
-
162
107
  /**
163
108
  * Converts spherical coordinates to cartesian coordinates.
164
109
  *
File without changes
package/src/util/async.js DELETED
@@ -1,29 +0,0 @@
1
- /*
2
- * Call an asynchronous function on an array of arguments,
3
- * calling `callback` with the completed results of all calls.
4
- *
5
- * @param array input to each call of the async function.
6
- * @param fn an async function with signature (data, callback)
7
- * @param callback a callback run after all async work is done.
8
- * called with an array, containing the results of each async call.
9
- * @private
10
- */
11
- export function all(array, fn, callback) {
12
- if (!array.length) {
13
- return callback(null, []);
14
- }
15
- let remaining = array.length;
16
- const results = new Array(array.length);
17
- let error = null;
18
- array.forEach((item, i) => {
19
- fn(item, (err, result) => {
20
- if (err) {
21
- error = err;
22
- }
23
- results[i] = result;
24
- if (--remaining === 0) {
25
- callback(error, results);
26
- }
27
- });
28
- });
29
- }
@@ -1,144 +0,0 @@
1
- import Point from '@mapbox/point-geometry';
2
- import Queue from 'tinyqueue';
3
- import { distToSegmentSquared } from './intersection_tests.js';
4
-
5
- /**
6
- * Finds an approximation of a polygon's Pole Of Inaccessibiliy https://en.wikipedia.org/wiki/Pole_of_inaccessibility
7
- * This is a copy of http://github.com/mapbox/polylabel adapted to use Points
8
- *
9
- * @param polygonRings first item in array is the outer ring followed optionally by the list of holes, should be an element of the result of util/classify_rings
10
- * @param precision Specified in input coordinate units. If 0 returns after first run, if > 0 repeatedly narrows the search space until the radius of the area searched for the best pole is less than precision
11
- * @param debug Print some statistics to the console during execution
12
- * @returns Pole of Inaccessibiliy.
13
- * @private
14
- */
15
- export default function (polygonRings, precision = 1, debug = false) {
16
- // find the bounding box of the outer ring
17
- let minX = Number.POSITIVE_INFINITY;
18
- let minY = Number.POSITIVE_INFINITY;
19
- let maxX = Number.NEGATIVE_INFINITY;
20
- let maxY = Number.NEGATIVE_INFINITY;
21
- const outerRing = polygonRings[0];
22
- for (let i = 0; i < outerRing.length; i++) {
23
- const p = outerRing[i];
24
- if (!i || p.x < minX) {
25
- minX = p.x;
26
- }
27
- if (!i || p.y < minY) {
28
- minY = p.y;
29
- }
30
- if (!i || p.x > maxX) {
31
- maxX = p.x;
32
- }
33
- if (!i || p.y > maxY) {
34
- maxY = p.y;
35
- }
36
- }
37
-
38
- const width = maxX - minX;
39
- const height = maxY - minY;
40
- const cellSize = Math.min(width, height);
41
- let h = cellSize / 2;
42
-
43
- // a priority queue of cells in order of their "potential" (max distance to polygon)
44
- const cellQueue = new Queue(undefined, compareMax);
45
-
46
- if (cellSize === 0) {
47
- return new Point(minX, minY);
48
- }
49
-
50
- // cover polygon with initial cells
51
- for (let x = minX; x < maxX; x += cellSize) {
52
- for (let y = minY; y < maxY; y += cellSize) {
53
- cellQueue.push(new Cell(x + h, y + h, h, polygonRings));
54
- }
55
- }
56
-
57
- // take centroid as the first best guess
58
- let bestCell = getCentroidCell(polygonRings);
59
- let numProbes = cellQueue.length;
60
-
61
- while (cellQueue.length) {
62
- // pick the most promising cell from the queue
63
- const cell = cellQueue.pop();
64
-
65
- // update the best cell if we found a better one
66
- if (cell.d > bestCell.d || !bestCell.d) {
67
- bestCell = cell;
68
- if (debug) {
69
- console.log('found best %d after %d probes', Math.round(1e4 * cell.d) / 1e4, numProbes);
70
- }
71
- }
72
-
73
- // do not drill down further if there's no chance of a better solution
74
- if (cell.max - bestCell.d <= precision) {
75
- continue;
76
- }
77
-
78
- // split the cell into four cells
79
- h = cell.h / 2;
80
- cellQueue.push(new Cell(cell.p.x - h, cell.p.y - h, h, polygonRings));
81
- cellQueue.push(new Cell(cell.p.x + h, cell.p.y - h, h, polygonRings));
82
- cellQueue.push(new Cell(cell.p.x - h, cell.p.y + h, h, polygonRings));
83
- cellQueue.push(new Cell(cell.p.x + h, cell.p.y + h, h, polygonRings));
84
- numProbes += 4;
85
- }
86
-
87
- if (debug) {
88
- console.log(`num probes: ${numProbes}`);
89
- console.log(`best distance: ${bestCell.d}`);
90
- }
91
-
92
- return bestCell.p;
93
- }
94
-
95
- function compareMax(a, b) {
96
- return b.max - a.max;
97
- }
98
-
99
- function Cell(x, y, h, polygon) {
100
- this.p = new Point(x, y);
101
- this.h = h; // half the cell size
102
- this.d = pointToPolygonDist(this.p, polygon); // distance from cell center to polygon
103
- this.max = this.d + this.h * Math.SQRT2; // max distance to polygon within a cell
104
- }
105
-
106
- // signed distance from point to polygon outline (negative if point is outside)
107
- function pointToPolygonDist(p, polygon) {
108
- let inside = false;
109
- let minDistSq = Number.POSITIVE_INFINITY;
110
-
111
- for (let k = 0; k < polygon.length; k++) {
112
- const ring = polygon[k];
113
-
114
- for (let i = 0, len = ring.length, j = len - 1; i < len; j = i++) {
115
- const a = ring[i];
116
- const b = ring[j];
117
-
118
- if (a.y > p.y !== b.y > p.y && p.x < ((b.x - a.x) * (p.y - a.y)) / (b.y - a.y) + a.x) {
119
- inside = !inside;
120
- }
121
-
122
- minDistSq = Math.min(minDistSq, distToSegmentSquared(p, a, b));
123
- }
124
- }
125
-
126
- return (inside ? 1 : -1) * Math.sqrt(minDistSq);
127
- }
128
-
129
- // get polygon centroid
130
- function getCentroidCell(polygon) {
131
- let area = 0;
132
- let x = 0;
133
- let y = 0;
134
- const points = polygon[0];
135
- for (let i = 0, len = points.length, j = len - 1; i < len; j = i++) {
136
- const a = points[i];
137
- const b = points[j];
138
- const f = a.x * b.y - b.x * a.y;
139
- x += (a.x + b.x) * f;
140
- y += (a.y + b.y) * f;
141
- area += f * 3;
142
- }
143
- return new Cell(x / area, y / area, 0, polygon);
144
- }