UNPKG

5.21 kBPlain TextView Raw
1import Point from '@mapbox/point-geometry';
2
3import StyleLayer from '../style_layer';
4import LineBucket from '../../data/bucket/line_bucket';
5import {polygonIntersectsBufferedMultiLine} from '../../util/intersection_tests';
6import {getMaximumPaintValue, translateDistance, translate, offsetLine} from '../query_utils';
7import properties, {LineLayoutPropsPossiblyEvaluated, LinePaintPropsPossiblyEvaluated} from './line_style_layer_properties.g';
8import {extend} from '../../util/util';
9import EvaluationParameters from '../evaluation_parameters';
10import {Transitionable, Transitioning, Layout, PossiblyEvaluated, DataDrivenProperty} from '../properties';
11
12import Step from '../../style-spec/expression/definitions/step';
13import type {FeatureState, ZoomConstantExpression} from '../../style-spec/expression';
14import type {Bucket, BucketParameters} from '../../data/bucket';
15import type {LineLayoutProps, LinePaintProps} from './line_style_layer_properties.g';
16import type Transform from '../../geo/transform';
17import type {LayerSpecification} from '../../style-spec/types.g';
18import type {VectorTileFeature} from '@mapbox/vector-tile';
19
20class LineFloorwidthProperty extends DataDrivenProperty<number> {
21 useIntegerZoom: true;
22
23 possiblyEvaluate(value, parameters) {
24 parameters = new EvaluationParameters(Math.floor(parameters.zoom), {
25 now: parameters.now,
26 fadeDuration: parameters.fadeDuration,
27 zoomHistory: parameters.zoomHistory,
28 transition: parameters.transition
29 });
30 return super.possiblyEvaluate(value, parameters);
31 }
32
33 evaluate(value, globals, feature, featureState) {
34 globals = extend({}, globals, {zoom: Math.floor(globals.zoom)});
35 return super.evaluate(value, globals, feature, featureState);
36 }
37}
38
39const lineFloorwidthProperty = new LineFloorwidthProperty(properties.paint.properties['line-width'].specification);
40lineFloorwidthProperty.useIntegerZoom = true;
41
42class LineStyleLayer extends StyleLayer {
43 _unevaluatedLayout: Layout<LineLayoutProps>;
44 layout: PossiblyEvaluated<LineLayoutProps, LineLayoutPropsPossiblyEvaluated>;
45
46 gradientVersion: number;
47 stepInterpolant: boolean;
48
49 _transitionablePaint: Transitionable<LinePaintProps>;
50 _transitioningPaint: Transitioning<LinePaintProps>;
51 paint: PossiblyEvaluated<LinePaintProps, LinePaintPropsPossiblyEvaluated>;
52
53 constructor(layer: LayerSpecification) {
54 super(layer, properties);
55 this.gradientVersion = 0;
56 }
57
58 _handleSpecialPaintPropertyUpdate(name: string) {
59 if (name === 'line-gradient') {
60 const expression: ZoomConstantExpression<'source'> = (this._transitionablePaint._values['line-gradient'].value.expression as any);
61 this.stepInterpolant = expression._styleExpression.expression instanceof Step;
62 this.gradientVersion = (this.gradientVersion + 1) % Number.MAX_SAFE_INTEGER;
63 }
64 }
65
66 gradientExpression() {
67 return this._transitionablePaint._values['line-gradient'].value.expression;
68 }
69
70 recalculate(parameters: EvaluationParameters, availableImages: Array<string>) {
71 super.recalculate(parameters, availableImages);
72
73 (this.paint._values as any)['line-floorwidth'] =
74 lineFloorwidthProperty.possiblyEvaluate(this._transitioningPaint._values['line-width'].value, parameters);
75 }
76
77 createBucket(parameters: BucketParameters<any>) {
78 return new LineBucket(parameters);
79 }
80
81 queryRadius(bucket: Bucket): number {
82 const lineBucket: LineBucket = (bucket as any);
83 const width = getLineWidth(
84 getMaximumPaintValue('line-width', this, lineBucket),
85 getMaximumPaintValue('line-gap-width', this, lineBucket));
86 const offset = getMaximumPaintValue('line-offset', this, lineBucket);
87 return width / 2 + Math.abs(offset) + translateDistance(this.paint.get('line-translate'));
88 }
89
90 queryIntersectsFeature(
91 queryGeometry: Array<Point>,
92 feature: VectorTileFeature,
93 featureState: FeatureState,
94 geometry: Array<Array<Point>>,
95 zoom: number,
96 transform: Transform,
97 pixelsToTileUnits: number
98 ): boolean {
99 const translatedPolygon = translate(queryGeometry,
100 this.paint.get('line-translate'),
101 this.paint.get('line-translate-anchor'),
102 transform.angle, pixelsToTileUnits);
103 const halfWidth = pixelsToTileUnits / 2 * getLineWidth(
104 this.paint.get('line-width').evaluate(feature, featureState),
105 this.paint.get('line-gap-width').evaluate(feature, featureState));
106 const lineOffset = this.paint.get('line-offset').evaluate(feature, featureState);
107 if (lineOffset) {
108 geometry = offsetLine(geometry, lineOffset * pixelsToTileUnits);
109 }
110
111 return polygonIntersectsBufferedMultiLine(translatedPolygon, geometry, halfWidth);
112 }
113
114 isTileClipped() {
115 return true;
116 }
117}
118
119export default LineStyleLayer;
120
121function getLineWidth(lineWidth, lineGapWidth) {
122 if (lineGapWidth > 0) {
123 return lineGapWidth + 2 * lineWidth;
124 } else {
125 return lineWidth;
126 }
127}