Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data-driven styling support for *-pattern properties #6289

Merged
merged 2 commits into from
Aug 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
.*/test/unit/style-spec/fixture/invalidjson.input.json
.*/test/integration/render-tests/.*
.*/test/build/downstream-flow-fixture/.*
.*/_batfish_site/.*

[version]
0.77.0
4 changes: 3 additions & 1 deletion build/generate-struct-arrays.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,16 @@ const circleAttributes = require('../src/data/bucket/circle_attributes').default
const fillAttributes = require('../src/data/bucket/fill_attributes').default;
const fillExtrusionAttributes = require('../src/data/bucket/fill_extrusion_attributes').default;
const lineAttributes = require('../src/data/bucket/line_attributes').default;
const patternAttributes = require('../src/data/bucket/pattern_attributes').default;

// layout vertex arrays
const layoutAttributes = {
circle: circleAttributes,
fill: fillAttributes,
'fill-extrusion': fillExtrusionAttributes,
heatmap: circleAttributes,
line: lineAttributes
line: lineAttributes,
pattern: patternAttributes
};
for (const name in layoutAttributes) {
createStructArrayType(`${name.replace(/-/g, '_')}_layout`, layoutAttributes[name]);
Expand Down
4 changes: 4 additions & 0 deletions build/generate-style-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ global.propertyType = function (property) {
return `DataDrivenProperty<${flowType(property)}>`;
case 'cross-faded':
return `CrossFadedProperty<${flowType(property)}>`;
case 'cross-faded-data-driven':
return `CrossFadedDataDrivenProperty<${flowType(property)}>`;
case 'color-ramp':
return `ColorRampProperty`;
case 'data-constant':
Expand Down Expand Up @@ -100,6 +102,8 @@ global.propertyValue = function (property, type) {
return `new DataDrivenProperty(styleSpec["${type}_${property.layerType}"]["${property.name}"])`;
case 'cross-faded':
return `new CrossFadedProperty(styleSpec["${type}_${property.layerType}"]["${property.name}"])`;
case 'cross-faded-data-driven':
return `new CrossFadedDataDrivenProperty(styleSpec["${type}_${property.layerType}"]["${property.name}"])`;
case 'color-ramp':
return `new ColorRampProperty(styleSpec["${type}_${property.layerType}"]["${property.name}"])`;
case 'data-constant':
Expand Down
50 changes: 50 additions & 0 deletions src/data/array_types.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,54 @@ StructArrayLayout4i4ub12.prototype.bytesPerElement = 12;
register('StructArrayLayout4i4ub12', StructArrayLayout4i4ub12);


/**
* Implementation of the StructArray layout:
* [0]: Uint16[8]
*
* @private
*/
class StructArrayLayout8ui16 extends StructArray {
uint8: Uint8Array;
uint16: Uint16Array;

_refreshViews() {
this.uint8 = new Uint8Array(this.arrayBuffer);
this.uint16 = new Uint16Array(this.arrayBuffer);
}

emplaceBack(v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number) {
const i = this.length;
this.resize(i + 1);
const o2 = i * 8;
this.uint16[o2 + 0] = v0;
this.uint16[o2 + 1] = v1;
this.uint16[o2 + 2] = v2;
this.uint16[o2 + 3] = v3;
this.uint16[o2 + 4] = v4;
this.uint16[o2 + 5] = v5;
this.uint16[o2 + 6] = v6;
this.uint16[o2 + 7] = v7;
return i;
}

emplace(i: number, v0: number, v1: number, v2: number, v3: number, v4: number, v5: number, v6: number, v7: number) {
const o2 = i * 8;
this.uint16[o2 + 0] = v0;
this.uint16[o2 + 1] = v1;
this.uint16[o2 + 2] = v2;
this.uint16[o2 + 3] = v3;
this.uint16[o2 + 4] = v4;
this.uint16[o2 + 5] = v5;
this.uint16[o2 + 6] = v6;
this.uint16[o2 + 7] = v7;
return i;
}
}

StructArrayLayout8ui16.prototype.bytesPerElement = 16;
register('StructArrayLayout8ui16', StructArrayLayout8ui16);


/**
* Implementation of the StructArray layout:
* [0]: Int16[4]
Expand Down Expand Up @@ -1187,6 +1235,7 @@ export {
StructArrayLayout4i8,
StructArrayLayout2i4i12,
StructArrayLayout4i4ub12,
StructArrayLayout8ui16,
StructArrayLayout4i4ui16,
StructArrayLayout3f12,
StructArrayLayout1ul4,
Expand All @@ -1210,6 +1259,7 @@ export {
StructArrayLayout2i4i12 as FillExtrusionLayoutArray,
StructArrayLayout2i4 as HeatmapLayoutArray,
StructArrayLayout4i4ub12 as LineLayoutArray,
StructArrayLayout8ui16 as PatternLayoutArray,
StructArrayLayout4i4ui16 as SymbolLayoutArray,
StructArrayLayout3f12 as SymbolDynamicLayoutArray,
StructArrayLayout1ul4 as SymbolOpacityArray,
Expand Down
15 changes: 14 additions & 1 deletion src/data/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {TypedStyleLayer} from '../style/style_layer/typed_style_layer';
import type FeatureIndex from './feature_index';
import type Context from '../gl/context';
import type {FeatureStates} from '../source/source_state';
import type {ImagePosition} from '../render/image_atlas';

export type BucketParameters<Layer: TypedStyleLayer> = {
index: number,
Expand All @@ -21,6 +22,7 @@ export type BucketParameters<Layer: TypedStyleLayer> = {
export type PopulateParameters = {
featureIndex: FeatureIndex,
iconDependencies: {},
patternDependencies: {},
glyphDependencies: {}
}

Expand All @@ -30,6 +32,16 @@ export type IndexedFeature = {
sourceLayerIndex: number,
}

export type BucketFeature = {|
index: number,
sourceLayerIndex: number,
geometry: Array<Array<Point>>,
properties: Object,
type: 1 | 2 | 3,
id?: any,
+patterns: {[string]: {"min": string, "mid": string, "max": string}}
|};

/**
* The `Bucket` interface is the single point of knowledge about turning vector
* tiles into WebGL buffers.
Expand All @@ -55,11 +67,12 @@ export type IndexedFeature = {
*/
export interface Bucket {
layerIds: Array<string>;
hasPattern: boolean;
+layers: Array<any>;
+stateDependentLayers: Array<any>;

populate(features: Array<IndexedFeature>, options: PopulateParameters): void;
update(states: FeatureStates, vtLayer: VectorTileLayer): void;
update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[string]: ImagePosition}): void;
isEmpty(): boolean;

upload(context: Context): void;
Expand Down
10 changes: 7 additions & 3 deletions src/data/bucket/circle_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import type IndexBuffer from '../../gl/index_buffer';
import type VertexBuffer from '../../gl/vertex_buffer';
import type Point from '@mapbox/point-geometry';
import type {FeatureStates} from '../../source/source_state';
import type {ImagePosition} from '../../render/image_atlas';


function addCircleVertex(layoutVertexArray, x, y, extrudeX, extrudeY) {
layoutVertexArray.emplaceBack(
Expand Down Expand Up @@ -53,6 +55,7 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
indexArray: TriangleIndexArray;
indexBuffer: IndexBuffer;

hasPattern: boolean;
programConfigurations: ProgramConfigurationSet<Layer>;
segments: SegmentVector;
uploaded: boolean;
Expand All @@ -63,6 +66,7 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
this.layers = options.layers;
this.layerIds = this.layers.map(layer => layer.id);
this.index = options.index;
this.hasPattern = false;

this.layoutVertexArray = new CircleLayoutArray();
this.indexArray = new TriangleIndexArray();
Expand All @@ -80,9 +84,9 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
}
}

update(states: FeatureStates, vtLayer: VectorTileLayer) {
update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[string]: ImagePosition}) {
if (!this.stateDependentLayers.length) return;
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers);
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
}

isEmpty() {
Expand Down Expand Up @@ -144,7 +148,7 @@ class CircleBucket<Layer: CircleStyleLayer | HeatmapStyleLayer> implements Bucke
}
}

this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index);
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, {});
}
}

Expand Down
56 changes: 45 additions & 11 deletions src/data/bucket/fill_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@ import { members as layoutAttributes } from './fill_attributes';
import SegmentVector from '../segment';
import { ProgramConfigurationSet } from '../program_configuration';
import { LineIndexArray, TriangleIndexArray } from '../index_array_type';
import loadGeometry from '../load_geometry';
import earcut from 'earcut';
import classifyRings from '../../util/classify_rings';
import assert from 'assert';
const EARCUT_MAX_RINGS = 500;
import { register } from '../../util/web_worker_transfer';
import {hasPattern, addPatternDependencies} from './pattern_bucket_features';
import loadGeometry from '../load_geometry';
import EvaluationParameters from '../../style/evaluation_parameters';

import type {
Bucket,
BucketParameters,
BucketFeature,
IndexedFeature,
PopulateParameters
} from '../bucket';
Expand All @@ -26,6 +28,7 @@ import type IndexBuffer from '../../gl/index_buffer';
import type VertexBuffer from '../../gl/vertex_buffer';
import type Point from '@mapbox/point-geometry';
import type {FeatureStates} from '../../source/source_state';
import type {ImagePosition} from '../../render/image_atlas';

class FillBucket implements Bucket {
index: number;
Expand All @@ -44,17 +47,20 @@ class FillBucket implements Bucket {
indexArray2: LineIndexArray;
indexBuffer2: IndexBuffer;

hasPattern: boolean;
programConfigurations: ProgramConfigurationSet<FillStyleLayer>;
segments: SegmentVector;
segments2: SegmentVector;
uploaded: boolean;
features: Array<BucketFeature>;

constructor(options: BucketParameters<FillStyleLayer>) {
this.zoom = options.zoom;
this.overscaling = options.overscaling;
this.layers = options.layers;
this.layerIds = this.layers.map(layer => layer.id);
this.index = options.index;
this.hasPattern = false;

this.layoutVertexArray = new FillLayoutArray();
this.indexArray = new TriangleIndexArray();
Expand All @@ -65,18 +71,47 @@ class FillBucket implements Bucket {
}

populate(features: Array<IndexedFeature>, options: PopulateParameters) {
this.features = [];
this.hasPattern = hasPattern('fill', this.layers, options);

for (const {feature, index, sourceLayerIndex} of features) {
if (this.layers[0]._featureFilter(new EvaluationParameters(this.zoom), feature)) {
const geometry = loadGeometry(feature);
this.addFeature(feature, geometry, index);
options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
if (!this.layers[0]._featureFilter(new EvaluationParameters(this.zoom), feature)) continue;

const geometry = loadGeometry(feature);

const patternFeature: BucketFeature = {
sourceLayerIndex: sourceLayerIndex,
index: index,
geometry: geometry,
properties: feature.properties,
type: feature.type,
patterns: {}
};

if (typeof feature.id !== 'undefined') {
patternFeature.id = feature.id;
}

if (this.hasPattern) {
this.features.push(addPatternDependencies('fill', this.layers, patternFeature, this.zoom, options));
} else {
this.addFeature(patternFeature, geometry, index, {});
}

options.featureIndex.insert(feature, geometry, index, sourceLayerIndex, this.index);
}
}

update(states: FeatureStates, vtLayer: VectorTileLayer) {
update(states: FeatureStates, vtLayer: VectorTileLayer, imagePositions: {[string]: ImagePosition}) {
if (!this.stateDependentLayers.length) return;
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers);
this.programConfigurations.updatePaintArrays(states, vtLayer, this.stateDependentLayers, imagePositions);
}

addFeatures(options: PopulateParameters, imagePositions: {[string]: ImagePosition}) {
for (const feature of this.features) {
const {geometry} = feature;
this.addFeature(feature, geometry, feature.index, imagePositions);
}
}

isEmpty() {
Expand Down Expand Up @@ -106,7 +141,7 @@ class FillBucket implements Bucket {
this.segments2.destroy();
}

addFeature(feature: VectorTileFeature, geometry: Array<Array<Point>>, index: number) {
addFeature(feature: BucketFeature, geometry: Array<Array<Point>>, index: number, imagePositions: {[string]: ImagePosition}) {
for (const polygon of classifyRings(geometry, EARCUT_MAX_RINGS)) {
let numVertices = 0;
for (const ring of polygon) {
Expand Down Expand Up @@ -160,11 +195,10 @@ class FillBucket implements Bucket {
triangleSegment.vertexLength += numVertices;
triangleSegment.primitiveLength += indices.length / 3;
}

this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index);
this.programConfigurations.populatePaintArrays(this.layoutVertexArray.length, feature, index, imagePositions);
}
}

register('FillBucket', FillBucket, {omit: ['layers']});
register('FillBucket', FillBucket, {omit: ['layers', 'features']});

export default FillBucket;
Loading