Skip to content

Commit af5f519

Browse files
committed
work on style projection expression
1 parent 881e357 commit af5f519

File tree

6 files changed

+71
-5
lines changed

6 files changed

+71
-5
lines changed

src/expression/definitions/interpolate.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import UnitBezier from '@mapbox/unitbezier';
22

33
import interpolate from '../../util/interpolate';
4-
import {array, ArrayType, ColorType, ColorTypeT, NumberType, NumberTypeT, PaddingType, PaddingTypeT, VariableAnchorOffsetCollectionType, VariableAnchorOffsetCollectionTypeT, toString, verifyType} from '../types';
4+
import {array, ArrayType, ColorType, ProjectionTypeT, ColorTypeT, NumberType, NumberTypeT, PaddingType, PaddingTypeT, VariableAnchorOffsetCollectionType, VariableAnchorOffsetCollectionTypeT, toString, verifyType, ProjectionType} from '../types';
55
import {findStopLessThanOrEqualTo} from '../stops';
66

77
import type {Stops} from '../stops';
@@ -19,18 +19,18 @@ export type InterpolationType = {
1919
name: 'cubic-bezier';
2020
controlPoints: [number, number, number, number];
2121
};
22-
type InterpolatedValueType = NumberTypeT | ColorTypeT | PaddingTypeT | VariableAnchorOffsetCollectionTypeT | ArrayType<NumberTypeT>;
22+
type InterpolatedValueType = NumberTypeT | ColorTypeT | ProjectionTypeT | PaddingTypeT | VariableAnchorOffsetCollectionTypeT | ArrayType<NumberTypeT>;
2323

2424
class Interpolate implements Expression {
2525
type: InterpolatedValueType;
2626

27-
operator: 'interpolate' | 'interpolate-hcl' | 'interpolate-lab';
27+
operator: 'interpolate' | 'interpolate-hcl' | 'interpolate-lab' | 'interpolate-projection';
2828
interpolation: InterpolationType;
2929
input: Expression;
3030
labels: Array<number>;
3131
outputs: Array<Expression>;
3232

33-
constructor(type: InterpolatedValueType, operator: 'interpolate' | 'interpolate-hcl' | 'interpolate-lab', interpolation: InterpolationType, input: Expression, stops: Stops) {
33+
constructor(type: InterpolatedValueType, operator: 'interpolate' | 'interpolate-hcl' | 'interpolate-lab' | 'interpolate-projection', interpolation: InterpolationType, input: Expression, stops: Stops) {
3434
this.type = type;
3535
this.operator = operator;
3636
this.interpolation = interpolation;
@@ -135,6 +135,7 @@ class Interpolate implements Expression {
135135

136136
if (!verifyType(outputType, NumberType) &&
137137
!verifyType(outputType, ColorType) &&
138+
!verifyType(outputType, ProjectionType) &&
138139
!verifyType(outputType, PaddingType) &&
139140
!verifyType(outputType, VariableAnchorOffsetCollectionType) &&
140141
!verifyType(outputType, array(NumberType))
@@ -174,6 +175,8 @@ class Interpolate implements Expression {
174175
switch (this.operator) {
175176
case 'interpolate':
176177
return interpolate[this.type.kind](outputLower, outputUpper, t);
178+
case 'interpolate-projection':
179+
return interpolate.projection(outputLower, outputUpper, t);
177180
case 'interpolate-hcl':
178181
return interpolate.color(outputLower, outputUpper, t, 'hcl');
179182
case 'interpolate-lab':

src/expression/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export type BooleanTypeT = {
1313
export type ColorTypeT = {
1414
kind: 'color';
1515
};
16+
export type ProjectionTypeT = {
17+
kind: 'string';
18+
};
1619
export type ObjectTypeT = {
1720
kind: 'object';
1821
};
@@ -40,7 +43,7 @@ export type VariableAnchorOffsetCollectionTypeT = {
4043

4144
export type EvaluationKind = 'constant' | 'source' | 'camera' | 'composite';
4245

43-
export type Type = NullTypeT | NumberTypeT | StringTypeT | BooleanTypeT | ColorTypeT | ObjectTypeT | ValueTypeT |
46+
export type Type = NullTypeT | NumberTypeT | StringTypeT | BooleanTypeT | ColorTypeT | ProjectionTypeT | ObjectTypeT | ValueTypeT |
4447
ArrayType | ErrorTypeT | CollatorTypeT | FormattedTypeT | PaddingTypeT | ResolvedImageTypeT | VariableAnchorOffsetCollectionTypeT;
4548

4649
export interface ArrayType<T extends Type = Type> {
@@ -56,6 +59,7 @@ export const NumberType = {kind: 'number'} as NumberTypeT;
5659
export const StringType = {kind: 'string'} as StringTypeT;
5760
export const BooleanType = {kind: 'boolean'} as BooleanTypeT;
5861
export const ColorType = {kind: 'color'} as ColorTypeT;
62+
export const ProjectionType = {kind: 'string'} as ProjectionTypeT;
5963
export const ObjectType = {kind: 'object'} as ObjectTypeT;
6064
export const ValueType = {kind: 'value'} as ValueTypeT;
6165
export const ErrorType = {kind: 'error'} as ErrorTypeT;
@@ -90,6 +94,7 @@ const valueMemberTypes = [
9094
StringType,
9195
BooleanType,
9296
ColorType,
97+
ProjectionType,
9398
FormattedType,
9499
ObjectType,
95100
array(ValueType),

src/util/interpolate.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Padding from './padding';
44
import VariableAnchorOffsetCollection from './variable_anchor_offset_collection';
55
import RuntimeError from '../expression/runtime_error';
66
import {VariableAnchorOffsetCollectionSpecification} from '../types.g';
7+
import {Projection} from './projection';
78

89
export type InterpolationColorSpace = 'rgb' | 'hcl' | 'lab';
910

@@ -37,6 +38,10 @@ function number(from: number, to: number, t: number): number {
3738
return from + t * (to - from);
3839
}
3940

41+
function projection(from: string, to: string, interpolation: number): Projection {
42+
return new Projection({from, to, interpolation});
43+
}
44+
4045
function color(from: Color, to: Color, t: number, spaceKey: InterpolationColorSpace = 'rgb'): Color {
4146
switch (spaceKey) {
4247
case 'rgb': {
@@ -122,6 +127,7 @@ function variableAnchorOffsetCollection(from: VariableAnchorOffsetCollection, to
122127
const interpolate = {
123128
number,
124129
color,
130+
projection,
125131
array,
126132
padding,
127133
variableAnchorOffsetCollection

src/util/projection.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {Projection} from './projection';
2+
3+
enum Proj {
4+
Mercator = 'mercator',
5+
Globe = 'globe'
6+
}
7+
8+
describe('Projection class', () => {
9+
10+
test('should serialize transition to string format', () => {
11+
expect(`${new Projection({from: Proj.Mercator, to: Proj.Globe, interpolation: 0.2})}`).toBe('["mercator-to-globe", 0.2]');
12+
expect(`${new Projection({from: Proj.Globe, to: Proj.Mercator, interpolation: 0.1})}`).toBe('["globe-to-mercator", 0.1]');
13+
});
14+
15+
test('should serialize single projection to string format', () => {
16+
expect(`${new Projection({projection: Proj.Mercator})}`).toBe('["mercator", 1]');
17+
expect(`${new Projection({projection: Proj.Globe})}`).toBe('["globe", 1]');
18+
});
19+
20+
});

src/util/projection.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export class Projection {
2+
projection: string;
3+
interpolation;
4+
5+
constructor(params: {projection: string} | { from: string; to: string; interpolation: number}) {
6+
7+
if ('projection' in params) {
8+
this.projection = params.projection;
9+
this.interpolation = 1;
10+
} else {
11+
const {from, to, interpolation} = params;
12+
this.projection = `${from}-to-${to}`;
13+
this.interpolation = interpolation;
14+
}
15+
}
16+
17+
toString(): string {
18+
return `["${this.projection}", ${this.interpolation}]`;
19+
}
20+
}

src/validate/validate_projection.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,17 @@ describe('Validate projection', () => {
4141
errors = validateProjection({validateSpec, value: {type: 'mercator'}, styleSpec: v8, style: {} as any});
4242
expect(errors).toHaveLength(0);
4343
});
44+
test('Should pass if everything is according to spec', () => {
45+
let errors = validateProjection({validateSpec, value: {type: ['interpolate', ['linear'], ['zoom'], 0, 'globe', 10, 'globe', 12, 'mercator']}, styleSpec: v8, style: {} as any});
46+
expect(errors).toHaveLength(0);
47+
errors = validateProjection({validateSpec, value: {type: 'mercator'}, styleSpec: v8, style: {} as any});
48+
expect(errors).toHaveLength(0);
49+
});
50+
test('Should not pass unknown proj', () => {
51+
let errors = validateProjection({validateSpec, value: {type: ['interpolate', ['linear'], ['zoom'], 0, 'unknown', 10, 'globe', 12, 'mercator']}, styleSpec: v8, style: {} as any});
52+
expect(errors).toHaveLength(0);
53+
errors = validateProjection({validateSpec, value: {type: 'mercator'}, styleSpec: v8, style: {} as any});
54+
expect(errors).toHaveLength(0);
55+
});
4456

4557
});

0 commit comments

Comments
 (0)