@mapwhit/tilerenderer 1.2.0 → 1.2.2

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 (36) hide show
  1. package/build/min/package.json +1 -1
  2. package/package.json +5 -5
  3. package/src/data/bucket/fill_extrusion_bucket.js +34 -39
  4. package/src/data/bucket/line_bucket.js +40 -48
  5. package/src/data/bucket/symbol_bucket.js +4 -5
  6. package/src/data/feature_index.js +10 -3
  7. package/src/geo/transform.js +13 -13
  8. package/src/index.js +1 -1
  9. package/src/source/geojson_wrapper.js +1 -9
  10. package/src/source/query_features.js +4 -1
  11. package/src/source/rtl_text_plugin.js +3 -1
  12. package/src/source/source_cache.js +3 -3
  13. package/src/source/tile.js +1 -1
  14. package/src/style/evaluation_parameters.js +5 -4
  15. package/src/style/query_utils.js +82 -7
  16. package/src/style/style.js +8 -2
  17. package/src/style/style_layer/circle_style_layer.js +26 -45
  18. package/src/style/style_layer/fill_extrusion_style_layer.js +26 -33
  19. package/src/style/style_layer/heatmap_style_layer.js +21 -7
  20. package/src/style/style_layer/line_style_layer.js +7 -7
  21. package/src/style/style_layer.js +3 -3
  22. package/src/style-spec/feature_filter/index.js +24 -19
  23. package/src/symbol/anchor.js +1 -1
  24. package/src/symbol/check_max_angle.js +6 -6
  25. package/src/symbol/collision_feature.js +9 -15
  26. package/src/symbol/collision_index.js +33 -27
  27. package/src/symbol/get_anchors.js +6 -5
  28. package/src/symbol/projection.js +3 -3
  29. package/src/symbol/quads.js +1 -1
  30. package/src/symbol/symbol_layout.js +1 -2
  31. package/src/ui/camera.js +1 -1
  32. package/src/ui/map.js +24 -24
  33. package/src/util/classify_rings.js +2 -4
  34. package/src/util/vectortile_to_geojson.js +65 -26
  35. package/build/min/src/shaders/.dir +0 -0
  36. package/src/symbol/clip_line.js +0 -72
@@ -1,4 +1,8 @@
1
- import Point from '@mapbox/point-geometry';
1
+ import glMatrix from '@mapbox/gl-matrix';
2
+ import { polygonIntersectsBufferedPoint } from '@mapwhit/geometry';
3
+ import { Point } from '@mapwhit/point-geometry';
4
+
5
+ const { vec4 } = glMatrix;
2
6
 
3
7
  export function getMaximumPaintValue(property, layer, bucket) {
4
8
  const value = layer._paint.get(property).value;
@@ -18,16 +22,87 @@ export function translate(queryGeometry, translate, translateAnchor, bearing, pi
18
22
  return queryGeometry;
19
23
  }
20
24
 
21
- const pt = Point.convert(translate)._mult(pixelsToTileUnits);
25
+ const pt = new Point(translate[0], translate[1])._mult(pixelsToTileUnits);
22
26
 
23
27
  if (translateAnchor === 'viewport') {
24
28
  pt._rotate(-bearing);
25
29
  }
26
30
 
27
- const translated = [];
28
- for (let i = 0; i < queryGeometry.length; i++) {
29
- const point = queryGeometry[i];
30
- translated.push(point.sub(pt));
31
+ pt;
32
+
33
+ return queryGeometry.map(point => point.sub(pt));
34
+ }
35
+
36
+ const circleIntersectionTests = new Map([
37
+ [
38
+ 'map',
39
+ new Map([
40
+ [
41
+ 'map',
42
+ ({ queryGeometry, point, size }) => {
43
+ return polygonIntersectsBufferedPoint(queryGeometry, point, size);
44
+ }
45
+ ],
46
+ [
47
+ 'viewport',
48
+ ({ queryGeometry, point, pixelPosMatrix, size, transform }) => {
49
+ const projectedCenter = vec4.transformMat4([], [point.x, point.y, 0, 1], pixelPosMatrix);
50
+ const adjustedSize = (size * projectedCenter[3]) / transform.cameraToCenterDistance;
51
+ return polygonIntersectsBufferedPoint(queryGeometry, point, adjustedSize);
52
+ }
53
+ ]
54
+ ])
55
+ ],
56
+ [
57
+ 'viewport',
58
+ new Map([
59
+ [
60
+ 'map',
61
+ ({ queryGeometry, point, pixelPosMatrix, size, transform }) => {
62
+ const projectedCenter = vec4.transformMat4([], [point.x, point.y, 0, 1], pixelPosMatrix);
63
+ const adjustedSize = (size * transform.cameraToCenterDistance) / projectedCenter[3];
64
+ return polygonIntersectsBufferedPoint(queryGeometry, projectPoint(point, pixelPosMatrix), adjustedSize);
65
+ }
66
+ ],
67
+ [
68
+ 'viewport',
69
+ ({ queryGeometry, point, pixelPosMatrix, size }) => {
70
+ return polygonIntersectsBufferedPoint(queryGeometry, projectPoint(point, pixelPosMatrix), size);
71
+ }
72
+ ]
73
+ ])
74
+ ]
75
+ ]);
76
+
77
+ export function circleIntersection({
78
+ queryGeometry,
79
+ geometry,
80
+ pixelPosMatrix,
81
+ size,
82
+ transform,
83
+ pitchAlignment = 'map',
84
+ pitchScale = 'map'
85
+ }) {
86
+ const intersectionTest = circleIntersectionTests.get(pitchAlignment).get(pitchScale);
87
+ const param = { queryGeometry, pixelPosMatrix, size, transform };
88
+ for (const ring of geometry) {
89
+ for (const point of ring) {
90
+ param.point = point;
91
+ if (intersectionTest(param)) {
92
+ return true;
93
+ }
94
+ }
31
95
  }
32
- return translated;
96
+ return false;
97
+ }
98
+
99
+ function projectPoint(p, pixelPosMatrix) {
100
+ const point = vec4.transformMat4([], [p.x, p.y, 0, 1], pixelPosMatrix);
101
+ return new Point(point[0] / point[3], point[1] / point[3]);
102
+ }
103
+
104
+ export function projectQueryGeometry(queryGeometry, pixelPosMatrix) {
105
+ return queryGeometry.map(p => {
106
+ return projectPoint(p, pixelPosMatrix);
107
+ });
33
108
  }
@@ -920,8 +920,9 @@ class Style extends Evented {
920
920
  }
921
921
 
922
922
  const sourceResults = [];
923
+ params = params ? { ...params, globalState: this._globalState } : { globalState: this._globalState };
923
924
  for (const id in this._sources) {
924
- if (params.layers && !includedSources[id]) {
925
+ if (params?.layers && !includedSources[id]) {
925
926
  continue;
926
927
  }
927
928
  sourceResults.push(
@@ -948,7 +949,12 @@ class Style extends Evented {
948
949
 
949
950
  querySourceFeatures(sourceID, params) {
950
951
  const sourceCache = this._sources[sourceID];
951
- return sourceCache ? querySourceFeatures(sourceCache, params) : [];
952
+ return sourceCache
953
+ ? querySourceFeatures(
954
+ sourceCache,
955
+ params ? { ...params, globalState: this._globalState } : { globalState: this._globalState }
956
+ )
957
+ : [];
952
958
  }
953
959
 
954
960
  getLight() {
@@ -1,14 +1,15 @@
1
- import glMatrix from '@mapbox/gl-matrix';
2
- import Point from '@mapbox/point-geometry';
3
- import { polygonIntersectsBufferedPoint } from '@mapwhit/geometry';
4
1
  import CircleBucket from '../../data/bucket/circle_bucket.js';
5
- import { getMaximumPaintValue, translate, translateDistance } from '../query_utils.js';
2
+ import {
3
+ circleIntersection,
4
+ getMaximumPaintValue,
5
+ projectQueryGeometry,
6
+ translate,
7
+ translateDistance
8
+ } from '../query_utils.js';
6
9
  import StyleLayer from '../style_layer.js';
7
10
  import properties from './circle_style_layer_properties.js';
8
11
 
9
- const { vec4 } = glMatrix;
10
-
11
- class CircleStyleLayer extends StyleLayer {
12
+ export default class CircleStyleLayer extends StyleLayer {
12
13
  constructor(layer, globalState) {
13
14
  super(layer, properties, globalState);
14
15
  }
@@ -51,48 +52,28 @@ class CircleStyleLayer extends StyleLayer {
51
52
  // // Otherwise, compare geometry in the plane of the viewport
52
53
  // // A circle with fixed scaling relative to the viewport gets larger in tile space as it moves into the distance
53
54
  // // A circle with fixed scaling relative to the map gets smaller in viewport space as it moves into the distance
55
+
54
56
  const pitchScale = this._paint.get('circle-pitch-scale');
55
57
  const pitchAlignment = this._paint.get('circle-pitch-alignment');
56
- const alignWithMap = pitchAlignment === 'map';
57
- const alignWithViewport = pitchAlignment === 'viewport';
58
- const transformedPolygon = alignWithMap
59
- ? translatedPolygon
60
- : projectQueryGeometry(translatedPolygon, pixelPosMatrix);
61
- const transformedSize = alignWithMap ? size * pixelsToTileUnits : size;
62
- const adjustViewportToMap = pitchScale === 'viewport' && alignWithMap;
63
- const adjustMapToViewport = pitchScale === 'map' && alignWithViewport;
64
-
65
- for (const ring of geometry) {
66
- for (const point of ring) {
67
- const transformedPoint = alignWithMap ? point : projectPoint(point, pixelPosMatrix);
68
58
 
69
- let adjustedSize = transformedSize;
70
- const projectedCenter = vec4.transformMat4([], [point.x, point.y, 0, 1], pixelPosMatrix);
71
- if (adjustViewportToMap) {
72
- adjustedSize *= projectedCenter[3] / transform.cameraToCenterDistance;
73
- } else if (adjustMapToViewport) {
74
- adjustedSize *= transform.cameraToCenterDistance / projectedCenter[3];
75
- }
76
-
77
- if (polygonIntersectsBufferedPoint(transformedPolygon, transformedPoint, adjustedSize)) {
78
- return true;
79
- }
80
- }
59
+ let transformedPolygon;
60
+ let transformedSize;
61
+ if (pitchAlignment === 'map') {
62
+ transformedPolygon = translatedPolygon;
63
+ transformedSize = size * pixelsToTileUnits;
64
+ } else {
65
+ transformedPolygon = projectQueryGeometry(translatedPolygon, pixelPosMatrix);
66
+ transformedSize = size;
81
67
  }
82
68
 
83
- return false;
69
+ return circleIntersection({
70
+ queryGeometry: transformedPolygon,
71
+ geometry,
72
+ pixelPosMatrix,
73
+ size: transformedSize,
74
+ transform,
75
+ pitchAlignment,
76
+ pitchScale
77
+ });
84
78
  }
85
79
  }
86
-
87
- function projectPoint(p, pixelPosMatrix) {
88
- const point = vec4.transformMat4([], [p.x, p.y, 0, 1], pixelPosMatrix);
89
- return new Point(point[0] / point[3], point[1] / point[3]);
90
- }
91
-
92
- function projectQueryGeometry(queryGeometry, pixelPosMatrix) {
93
- return queryGeometry.map(p => {
94
- return projectPoint(p, pixelPosMatrix);
95
- });
96
- }
97
-
98
- export default CircleStyleLayer;
@@ -1,6 +1,6 @@
1
1
  import glMatrix from '@mapbox/gl-matrix';
2
- import Point from '@mapbox/point-geometry';
3
2
  import { polygonIntersectsMultiPolygon, polygonIntersectsPolygon } from '@mapwhit/geometry';
3
+ import { clone, equals, sub } from '@mapwhit/point-geometry';
4
4
  import FillExtrusionBucket from '../../data/bucket/fill_extrusion_bucket.js';
5
5
  import { translate, translateDistance } from '../query_utils.js';
6
6
  import StyleLayer from '../style_layer.js';
@@ -45,11 +45,9 @@ export class FillExtrusionStyleLayer extends StyleLayer {
45
45
  const height = this._paint.get('fill-extrusion-height').evaluate(feature, featureState);
46
46
  const base = this._paint.get('fill-extrusion-base').evaluate(feature, featureState);
47
47
 
48
- const projectedQueryGeometry = projectQueryGeometry(translatedPolygon, pixelPosMatrix, transform, 0);
48
+ const projectedQueryGeometry = projectQueryGeometry(translatedPolygon, pixelPosMatrix, 0);
49
49
 
50
- const projected = projectExtrusion(geometry, base, height, pixelPosMatrix);
51
- const projectedBase = projected[0];
52
- const projectedTop = projected[1];
50
+ const { projectedBase, projectedTop } = projectExtrusion(geometry, base, height, pixelPosMatrix);
53
51
  return checkIntersection(projectedBase, projectedTop, projectedQueryGeometry);
54
52
  }
55
53
  }
@@ -72,7 +70,7 @@ export function getIntersectionDistance(projectedQueryGeometry, projectedFace) {
72
70
  let i = 0;
73
71
  const a = projectedFace[i++];
74
72
  let b;
75
- while (!b || a.equals(b)) {
73
+ while (!b || equals(a, b)) {
76
74
  b = projectedFace[i++];
77
75
  if (!b) {
78
76
  return Number.POSITIVE_INFINITY;
@@ -84,9 +82,9 @@ export function getIntersectionDistance(projectedQueryGeometry, projectedFace) {
84
82
  const c = projectedFace[i];
85
83
  const p = projectedQueryGeometry[0];
86
84
 
87
- const ab = b.sub(a);
88
- const ac = c.sub(a);
89
- const ap = p.sub(a);
85
+ const ab = sub(clone(b), a);
86
+ const ac = sub(clone(c), a);
87
+ const ap = sub(clone(p), a);
90
88
 
91
89
  const dotABAB = dot(ab, ab);
92
90
  const dotABAC = dot(ab, ac);
@@ -153,8 +151,8 @@ function checkIntersection(projectedBase, projectedTop, projectedQueryGeometry)
153
151
  * performance improvement.
154
152
  */
155
153
  function projectExtrusion(geometry, zBase, zTop, m) {
156
- const projectedBase = [];
157
- const projectedTop = [];
154
+ const projectedBase = new Array(geometry.length);
155
+ const projectedTop = new Array(geometry.length);
158
156
 
159
157
  const baseXZ = m[8] * zBase;
160
158
  const baseYZ = m[9] * zBase;
@@ -165,12 +163,12 @@ function projectExtrusion(geometry, zBase, zTop, m) {
165
163
  const topZZ = m[10] * zTop;
166
164
  const topWZ = m[11] * zTop;
167
165
 
168
- for (const r of geometry) {
169
- const ringBase = [];
170
- const ringTop = [];
171
- for (const p of r) {
172
- const x = p.x;
173
- const y = p.y;
166
+ for (let i = 0; i < geometry.length; i++) {
167
+ const ring = geometry[i];
168
+ const ringBase = new Array(ring.length);
169
+ const ringTop = new Array(ring.length);
170
+ for (let j = 0; j < ring.length; j++) {
171
+ const { x, y } = ring[j];
174
172
 
175
173
  const sX = m[0] * x + m[4] * y + m[12];
176
174
  const sY = m[1] * x + m[5] * y + m[13];
@@ -181,32 +179,27 @@ function projectExtrusion(geometry, zBase, zTop, m) {
181
179
  const baseY = sY + baseYZ;
182
180
  const baseZ = sZ + baseZZ;
183
181
  const baseW = sW + baseWZ;
182
+ ringBase[j] = { x: baseX / baseW, y: baseY / baseW, z: baseZ / baseW };
184
183
 
185
184
  const topX = sX + topXZ;
186
185
  const topY = sY + topYZ;
187
186
  const topZ = sZ + topZZ;
188
187
  const topW = sW + topWZ;
189
-
190
- const b = new Point(baseX / baseW, baseY / baseW);
191
- b.z = baseZ / baseW;
192
- ringBase.push(b);
193
-
194
- const t = new Point(topX / topW, topY / topW);
195
- t.z = topZ / topW;
196
- ringTop.push(t);
188
+ ringTop[j] = { x: topX / topW, y: topY / topW, z: topZ / topW };
197
189
  }
198
- projectedBase.push(ringBase);
199
- projectedTop.push(ringTop);
190
+ projectedBase[i] = ringBase;
191
+ projectedTop[i] = ringTop;
200
192
  }
201
- return [projectedBase, projectedTop];
193
+ return { projectedBase, projectedTop };
202
194
  }
203
195
 
204
- function projectQueryGeometry(queryGeometry, pixelPosMatrix, transform, z) {
205
- const projectedQueryGeometry = [];
206
- for (const p of queryGeometry) {
207
- const v = [p.x, p.y, z, 1];
196
+ function projectQueryGeometry(queryGeometry, pixelPosMatrix, z) {
197
+ const projectedQueryGeometry = new Array(queryGeometry.length);
198
+ for (let i = 0; i < queryGeometry.length; i++) {
199
+ const { x, y } = queryGeometry[i];
200
+ const v = [x, y, z, 1];
208
201
  vec4.transformMat4(v, v, pixelPosMatrix);
209
- projectedQueryGeometry.push(new Point(v[0] / v[3], v[1] / v[3]));
202
+ projectedQueryGeometry[i] = { x: v[0] / v[3], y: v[1] / v[3] };
210
203
  }
211
204
  return projectedQueryGeometry;
212
205
  }
@@ -1,9 +1,10 @@
1
1
  import HeatmapBucket from '../../data/bucket/heatmap_bucket.js';
2
2
  import renderColorRamp from '../../util/color_ramp.js';
3
+ import { circleIntersection, getMaximumPaintValue } from '../query_utils.js';
3
4
  import StyleLayer from '../style_layer.js';
4
5
  import properties from './heatmap_style_layer_properties.js';
5
6
 
6
- class HeatmapStyleLayer extends StyleLayer {
7
+ export default class HeatmapStyleLayer extends StyleLayer {
7
8
  createBucket(options) {
8
9
  return new HeatmapBucket(options);
9
10
  }
@@ -34,17 +35,30 @@ class HeatmapStyleLayer extends StyleLayer {
34
35
  }
35
36
  }
36
37
 
37
- queryRadius() {
38
- return 0;
38
+ queryRadius(bucket) {
39
+ return getMaximumPaintValue('heatmap-radius', this, bucket);
39
40
  }
40
41
 
41
- queryIntersectsFeature() {
42
- return false;
42
+ queryIntersectsFeature(
43
+ queryGeometry,
44
+ feature,
45
+ featureState,
46
+ geometry,
47
+ zoom,
48
+ transform,
49
+ pixelsToTileUnits,
50
+ pixelPosMatrix
51
+ ) {
52
+ return circleIntersection({
53
+ queryGeometry,
54
+ geometry,
55
+ pixelPosMatrix,
56
+ size: this._paint.get('heatmap-radius').evaluate(feature, featureState) * pixelsToTileUnits,
57
+ transform
58
+ });
43
59
  }
44
60
 
45
61
  hasOffscreenPass() {
46
62
  return this._paint.get('heatmap-opacity') !== 0 && !this.isHidden();
47
63
  }
48
64
  }
49
-
50
- export default HeatmapStyleLayer;
@@ -1,5 +1,5 @@
1
- import Point from '@mapbox/point-geometry';
2
1
  import { polygonIntersectsBufferedMultiLine } from '@mapwhit/geometry';
2
+ import { add, clone, div, mult, perp, sub, unit } from '@mapwhit/point-geometry';
3
3
  import LineBucket from '../../data/bucket/line_bucket.js';
4
4
  import renderColorRamp from '../../util/color_ramp.js';
5
5
  import EvaluationParameters from '../evaluation_parameters.js';
@@ -111,22 +111,22 @@ function offsetLine(rings, offset) {
111
111
  newRings[k] = newRing;
112
112
 
113
113
  let b = ring[0];
114
- let aToB = new Point(0, 0);
114
+ let aToB = { x: 0, y: 0 };
115
115
  for (let i = 0; i < ring.length - 1; i++) {
116
116
  const c = ring[i + 1];
117
- const bToC = c.sub(b)._unit()._perp();
118
- const extrude = aToB._add(bToC)._unit();
117
+ const bToC = perp(unit(sub(clone(c), b)));
118
+ const extrude = unit(add(aToB, bToC));
119
119
  const cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y;
120
120
  if (cosHalfAngle !== 0) {
121
- extrude._div(cosHalfAngle);
121
+ div(extrude, cosHalfAngle);
122
122
  }
123
- newRing[i] = extrude._mult(offset)._add(b);
123
+ newRing[i] = add(mult(extrude, offset), b);
124
124
 
125
125
  b = c;
126
126
  aToB = bToC;
127
127
  }
128
128
 
129
- newRing[ring.length - 1] = aToB._unit()._mult(offset)._add(b);
129
+ newRing[ring.length - 1] = add(mult(unit(aToB), offset), b);
130
130
  }
131
131
  return newRings;
132
132
  }
@@ -35,10 +35,10 @@ class StyleLayer extends Evented {
35
35
  this.source = layer.source;
36
36
  this['source-layer'] = this.sourceLayer = layer['source-layer'];
37
37
  this.filter = layer.filter;
38
- this._featureFilter = featureFilter(layer.filter);
38
+ this._featureFilter = featureFilter(layer.filter, globalState);
39
39
  }
40
40
 
41
- this._featureFilter ??= featureFilter.addGlobalStateRefs(() => true);
41
+ this._featureFilter ??= featureFilter(undefined, globalState);
42
42
 
43
43
  if (properties.layout) {
44
44
  this._unevaluatedLayout = new Layout(properties.layout, globalState);
@@ -59,7 +59,7 @@ class StyleLayer extends Evented {
59
59
  setFilter(filter) {
60
60
  this.#key = undefined;
61
61
  this.filter = filter;
62
- this._featureFilter = featureFilter(filter);
62
+ this._featureFilter.setValue(filter);
63
63
  }
64
64
 
65
65
  _setZoomRange(minzoom, maxzoom) {
@@ -64,29 +64,34 @@ const filterSpec = {
64
64
  * @returns {Function} filter-evaluating function
65
65
  */
66
66
  export default function createFilter(filter, globalState) {
67
- if (filter === null || filter === undefined) {
68
- return addGlobalStateRefs(() => true);
67
+ let evaluate;
68
+ const expression = (globalProperties, feature) => evaluate(globalProperties, feature);
69
+ expression.setValue = setValue;
70
+ setValue(filter);
71
+ return expression;
72
+
73
+ function setValue(filter) {
74
+ if (filter === null || filter === undefined) {
75
+ evaluate = () => true;
76
+ addGlobalStateRefs(expression);
77
+ return;
78
+ }
79
+
80
+ if (!isExpressionFilter(filter)) {
81
+ filter = convertFilter(filter);
82
+ }
83
+
84
+ const compiled = createExpression(filter, filterSpec, globalState);
85
+ if (compiled.result === 'error') {
86
+ throw new Error(compiled.value.map(err => `${err.key}: ${err.message}`).join(', '));
87
+ }
88
+ evaluate = (globalProperties, feature) => compiled.value.evaluate(globalProperties, feature);
89
+ addGlobalStateRefs(expression, () => findGlobalStateRefs(compiled.value.expression));
69
90
  }
70
-
71
- if (!isExpressionFilter(filter)) {
72
- filter = convertFilter(filter);
73
- }
74
-
75
- const compiled = createExpression(filter, filterSpec, globalState);
76
- if (compiled.result === 'error') {
77
- throw new Error(compiled.value.map(err => `${err.key}: ${err.message}`).join(', '));
78
- }
79
- return Object.assign(
80
- addGlobalStateRefs(
81
- (globalProperties, feature) => compiled.value.evaluate(globalProperties, feature),
82
- () => findGlobalStateRefs(compiled.value.expression)
83
- )
84
- );
85
91
  }
86
92
 
87
- export function addGlobalStateRefs(filter, getGlobalStateRefs = () => new Set()) {
93
+ function addGlobalStateRefs(filter, getGlobalStateRefs = () => new Set()) {
88
94
  filter.getGlobalStateRefs = getGlobalStateRefs;
89
- return filter;
90
95
  }
91
96
 
92
97
  // Comparison function to sort numbers and strings
@@ -1,4 +1,4 @@
1
- import Point from '@mapbox/point-geometry';
1
+ import { Point } from '@mapwhit/point-geometry';
2
2
 
3
3
  class Anchor extends Point {
4
4
  constructor(x, y, angle, segment) {
@@ -1,4 +1,4 @@
1
- export default checkMaxAngle;
1
+ import { angleTo, dist } from '@mapwhit/point-geometry';
2
2
 
3
3
  /**
4
4
  * Labels placed around really sharp angles aren't readable. Check if any
@@ -13,7 +13,7 @@ export default checkMaxAngle;
13
13
  * @returns {boolean} whether the label should be placed
14
14
  * @private
15
15
  */
16
- function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) {
16
+ export default function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) {
17
17
  // horizontal labels always pass
18
18
  if (anchor.segment === undefined) {
19
19
  return true;
@@ -32,11 +32,11 @@ function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) {
32
32
  return false;
33
33
  }
34
34
 
35
- anchorDistance -= line[index].dist(p);
35
+ anchorDistance -= dist(line[index], p);
36
36
  p = line[index];
37
37
  }
38
38
 
39
- anchorDistance += line[index].dist(line[index + 1]);
39
+ anchorDistance += dist(line[index], line[index + 1]);
40
40
  index++;
41
41
 
42
42
  // store recent corners and their total angle difference
@@ -54,7 +54,7 @@ function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) {
54
54
  return false;
55
55
  }
56
56
 
57
- let angleDelta = prev.angleTo(current) - current.angleTo(next);
57
+ let angleDelta = angleTo(prev, current) - angleTo(current, next);
58
58
  // restrict angle to -pi..pi range
59
59
  angleDelta = Math.abs(((angleDelta + 3 * Math.PI) % (Math.PI * 2)) - Math.PI);
60
60
 
@@ -75,7 +75,7 @@ function checkMaxAngle(line, anchor, labelLength, windowSize, maxAngle) {
75
75
  }
76
76
 
77
77
  index++;
78
- anchorDistance += current.dist(next);
78
+ anchorDistance += dist(current, next);
79
79
  }
80
80
 
81
81
  // no part of the line had an angle greater than the maximum allowed. check passes.
@@ -1,4 +1,4 @@
1
- import Point from '@mapbox/point-geometry';
1
+ import { dist, Point, rotate as rotatePoint } from '@mapwhit/point-geometry';
2
2
 
3
3
  /**
4
4
  * A CollisionFeature represents the area of the tile covered by a single label.
@@ -67,17 +67,11 @@ class CollisionFeature {
67
67
  // See https://github.com/mapbox/mapbox-gl-js/issues/6075
68
68
  // Doesn't account for icon-text-fit
69
69
 
70
- const tl = new Point(x1, y1);
71
- const tr = new Point(x2, y1);
72
- const bl = new Point(x1, y2);
73
- const br = new Point(x2, y2);
74
-
75
70
  const rotateRadians = (rotate * Math.PI) / 180;
76
-
77
- tl._rotate(rotateRadians);
78
- tr._rotate(rotateRadians);
79
- bl._rotate(rotateRadians);
80
- br._rotate(rotateRadians);
71
+ const tl = rotatePoint({ x: x1, y: y1 }, rotateRadians);
72
+ const tr = rotatePoint({ x: x2, y: y1 }, rotateRadians);
73
+ const bl = rotatePoint({ x: x1, y: y2 }, rotateRadians);
74
+ const br = rotatePoint({ x: x2, y: y2 }, rotateRadians);
81
75
 
82
76
  // Collision features require an "on-axis" geometry,
83
77
  // so take the envelope of the rotated geometry
@@ -162,11 +156,11 @@ class CollisionFeature {
162
156
  index = 0;
163
157
  break;
164
158
  }
165
- anchorDistance -= line[index].dist(p);
159
+ anchorDistance -= dist(line[index], p);
166
160
  p = line[index];
167
161
  } while (anchorDistance > paddingStartDistance);
168
162
 
169
- let segmentLength = line[index].dist(line[index + 1]);
163
+ let segmentLength = dist(line[index], line[index + 1]);
170
164
 
171
165
  for (let i = -nPitchPaddingBoxes; i < nBoxes + nPitchPaddingBoxes; i++) {
172
166
  // the distance the box will be from the anchor
@@ -197,7 +191,7 @@ class CollisionFeature {
197
191
  return;
198
192
  }
199
193
 
200
- segmentLength = line[index].dist(line[index + 1]);
194
+ segmentLength = dist(line[index], line[index + 1]);
201
195
  }
202
196
 
203
197
  // the distance the box will be from the beginning of the segment
@@ -205,7 +199,7 @@ class CollisionFeature {
205
199
 
206
200
  const p0 = line[index];
207
201
  const p1 = line[index + 1];
208
- const boxAnchorPoint = p1.sub(p0)._unit()._mult(segmentBoxDistance)._add(p0)._round();
202
+ const boxAnchorPoint = Point.clone(p1)._sub(p0)._unit()._mult(segmentBoxDistance)._add(p0)._round();
209
203
 
210
204
  // If the box is within boxSize of the anchor, force the box to be used
211
205
  // (so even 0-width labels use at least one box)