Skip to content

Commit

Permalink
Integrate geojson-vt line-metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
Lauren Budorick committed Mar 8, 2018
1 parent a492d2a commit 1ae9400
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 44 deletions.
3 changes: 2 additions & 1 deletion flow-typed/style-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ declare type GeojsonSourceSpecification = {|
"tolerance"?: number,
"cluster"?: boolean,
"clusterRadius"?: number,
"clusterMaxZoom"?: number
"clusterMaxZoom"?: number,
"lineMetrics"?: boolean
|}

declare type VideoSourceSpecification = {|
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"csscolorparser": "~1.0.2",
"earcut": "^2.1.3",
"geojson-rewind": "^0.3.0",
"geojson-vt": "^3.0.0",
"geojson-vt": "git://github.com/mapbox/geojson-vt.git#line-metrics",
"gray-matter": "^3.0.8",
"grid-index": "^1.0.0",
"jsonlint-lines-primitives": "~1.6.0",
Expand Down
48 changes: 24 additions & 24 deletions src/data/bucket/line_bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,12 @@ class LineBucket implements Bucket {
addLine(vertices: Array<Point>, feature: VectorTileFeature, join: string, cap: string, miterLimit: number, roundLimit: number) {
let lineDistances = null;
if (!!feature.properties &&
feature.properties.hasOwnProperty('$distance_total') &&
feature.properties.hasOwnProperty('$distance_start')) {
feature.properties.hasOwnProperty('$distance_start') &&
feature.properties.hasOwnProperty('$distance_end')) {
lineDistances = {
total: feature.properties.$distance_total,
start: feature.properties.$distance_start
start: feature.properties.$distance_start,
end: feature.properties.$distance_end,
tileTotal: undefined
};
}

Expand All @@ -181,6 +182,10 @@ class LineBucket implements Bucket {
// Ignore invalid geometry.
if (len < (isPolygon ? 3 : 2)) return;

if (lineDistances) {
lineDistances.tileTotal = calculateFullDistance(vertices, first, len);
}

if (join === 'bevel') miterLimit = 1.05;

const sharpCornerOffset = SHARP_CORNER_OFFSET * (EXTENT / (512 * this.overscaling));
Expand Down Expand Up @@ -454,15 +459,8 @@ class LineBucket implements Bucket {
const indexArray = this.indexArray;

if (distancesForScaling) {
// First scale line from tile units to [0, 2^15)
distance = this.scaleDistance(distance, distancesForScaling);
// Check to see if this vertex is going to be drawn across an edge,
// and if so, don't add square/round caps:
if (this.shouldClipAtEdge(currentVertex, distance)) {
round = false;
endLeft = 0;
endRight = 0;
}
// Scale line from tile units to [0, 2^15)
distance = scaleDistance(distance, distancesForScaling);
}

extrude = normal.clone();
Expand Down Expand Up @@ -517,7 +515,7 @@ class LineBucket implements Bucket {
const layoutVertexArray = this.layoutVertexArray;
const indexArray = this.indexArray;

if (distancesForScaling) distance = this.scaleDistance(distance, distancesForScaling);
if (distancesForScaling) distance = scaleDistance(distance, distancesForScaling);

addLineVertex(layoutVertexArray, currentVertex, extrude, false, lineTurnsLeft, 0, distance);
this.e3 = segment.vertexLength++;
Expand All @@ -532,19 +530,21 @@ class LineBucket implements Bucket {
this.e1 = this.e3;
}
}
}

scaleDistance(tileDistance: number, stats: Object) {
return (stats.start + tileDistance) * ((MAX_LINE_DISTANCE - 1) / stats.total);
}
function scaleDistance(tileDistance: number, stats: Object) {
return ((tileDistance / stats.tileTotal) * (stats.end - stats.start) + stats.start) * (MAX_LINE_DISTANCE - 1);
}

shouldClipAtEdge(vertex: Point, distance: number): boolean {
// We detect non-start/end tile edge vertices for gradient lines because
// we turn clipping off when there's no tile buffer (which we do in
// order to calcuate line distances correctly), and turn these into butt
// ends so they won't overlap with semitransparent neighbors.
if (distance === 0 || distance === MAX_LINE_DISTANCE - 1) return false;
return vertex.x === 0 || vertex.x === EXTENT || vertex.y === 0 || vertex.y === EXTENT;
function calculateFullDistance(vertices: Array<Point>, first: number, len: number) {
let currentVertex, nextVertex;
let total = 0;
for (let i = first; i < len - 1; i++) {
currentVertex = vertices[i];
nextVertex = vertices[i + 1];
total += currentVertex.dist(nextVertex);
}
return total;
}

register('LineBucket', LineBucket, {omit: ['layers']});
Expand Down
3 changes: 2 additions & 1 deletion src/source/geojson_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ class GeoJSONSource extends Evented implements Source {
buffer: (options.buffer !== undefined ? options.buffer : 128) * scale,
tolerance: (options.tolerance !== undefined ? options.tolerance : 0.375) * scale,
extent: EXTENT,
maxZoom: this.maxzoom
maxZoom: this.maxzoom,
lineMetrics: options.lineMetrics
},
superclusterOptions: {
maxZoom: options.clusterMaxZoom !== undefined ?
Expand Down
13 changes: 12 additions & 1 deletion src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,11 @@
"clusterMaxZoom": {
"type": "number",
"doc": "Max zoom on which to cluster points if clustering is enabled. Defaults to one zoom less than maxzoom (so that last zoom features are not clustered)."
},
"lineMetrics": {
"type": "boolean",
"default": false,
"doc": "Whether to calculate line distance metrics. This is required for line layers that specify `line-gradient` values."
}
},
"source_video": {
Expand Down Expand Up @@ -2961,7 +2966,7 @@
},
"line-gradient": {
"type": "color",
"doc": "Defines a gradient with which to color a line feature. Can only be used with GeoJSON sources.",
"doc": "Defines a gradient with which to color a line feature. Can only be used with GeoJSON sources that specify `\"lineMetrics\": true`.",
"function": "interpolated",
"zoom-function": false,
"property-function": false,
Expand All @@ -2972,6 +2977,12 @@
},
{
"!": "line-pattern"
},
{
"source": "geojson",
"has": {
"lineMetrics": true
}
}
],
"sdk-support": {
Expand Down
5 changes: 3 additions & 2 deletions src/style-spec/validate/validate_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ module.exports = function validateLayer(options) {
errors.push(new ValidationError(key, layer, `layer "${layer.id}" must specify a "source-layer"`));
} else if (sourceType === 'raster-dem' && type !== 'hillshade') {
errors.push(new ValidationError(key, layer.source, 'raster-dem source can only be used with layer type \'hillshade\'.'));
} else if (sourceType !== 'geojson' && type === 'line' && layer.paint && layer.paint['line-gradient']) {
errors.push(new ValidationError(key, layer, `layer "${layer.id}" specifies a line-gradient, which requires a GeoJSON source`));
} else if (type === 'line' && layer.paint && layer.paint['line-gradient'] &&
(sourceType !== 'geojson' || !source.lineMetrics)) {
errors.push(new ValidationError(key, layer, `layer "${layer.id}" specifies a line-gradient, which requires a GeoJSON source with \`lineMetrics\` enabled.`));
}
}
}
Expand Down
Binary file modified test/integration/render-tests/line-gradient/gradient/expected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 43 additions & 7 deletions test/integration/render-tests/line-gradient/gradient/style.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,56 @@
"zoom": 2,
"sources": {
"gradient": {
"type": "vector",
"tiles": [
"local://tiles/{z}-{x}-{y}-gradient.vector.pbf"
],
"maxzoom": 6,
"tileSize": 512
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
-1,
8
],
[
8,
1
],
[
1,
-8
],
[
-8,
-1
],
[
1,
4
],
[
4,
-1
],
[
-1,
-4
],
[
-2,
0
]
]
}
},
"lineMetrics": true
}
},
"layers": [
{
"id": "line",
"type": "line",
"source": "gradient",
"source-layer": "line",
"layout": {
"line-cap": "round",
"line-join": "round"
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 43 additions & 7 deletions test/integration/render-tests/line-gradient/translucent/style.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,56 @@
"zoom": 2,
"sources": {
"gradient": {
"type": "vector",
"tiles": [
"local://tiles/{z}-{x}-{y}-gradient.vector.pbf"
],
"maxzoom": 6,
"tileSize": 512
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
-1,
8
],
[
8,
1
],
[
1,
-8
],
[
-8,
-1
],
[
1,
4
],
[
4,
-1
],
[
-1,
-4
],
[
-2,
0
]
]
}
},
"lineMetrics": true
}
},
"layers": [
{
"id": "line",
"type": "line",
"source": "gradient",
"source-layer": "line",
"layout": {
"line-cap": "round",
"line-join": "round"
Expand Down

0 comments on commit 1ae9400

Please sign in to comment.