Skip to content

Commit

Permalink
v8.0 TripsLayer API change (#3874)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pessimistress committed Nov 12, 2019
1 parent 92b047f commit 89aa08d
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 75 deletions.
2 changes: 2 additions & 0 deletions docs/layers/trips-layer.md
Expand Up @@ -104,6 +104,8 @@ See [PathLayer](/docs/layers/path-layer.md) documentation for supported path for

##### `getTimestamps` ([Function](/docs/developer-guide/using-layers.md#accessors), optional)

- Default: `d => d.timestamps`

Returns an array of timestamps, one for each navigation point in the geometry returned by `getPath`, representing the time that the point is visited.

Because timestamps are stored as 32-bit floating numbers, raw unix epoch time can not be used. You may test the validity of a timestamp by calling `Math.fround(t)` to check if there would be any loss of precision.
Expand Down
4 changes: 2 additions & 2 deletions examples/layer-browser/src/examples/additional-layers.js
Expand Up @@ -84,8 +84,8 @@ const TripsLayerExample = {
props: {
id: 'trips-layer',
data: dataSamples.SFTrips,
getPath: d =>
d.waypoints.map(p => [p.coordinates[0], p.coordinates[1], p.timestamp - 1554772579000]),
getPath: d => d.waypoints.map(p => p.coordinates),
getTimestamps: d => d.waypoints.map(p => p.timestamp - 1554772579000),
getColor: [253, 128, 93],
opacity: 0.8,
widthMinPixels: 5,
Expand Down
40 changes: 10 additions & 30 deletions modules/geo-layers/src/trips-layer/trips-layer.js
Expand Up @@ -19,7 +19,7 @@
// THE SOFTWARE.

import {PathLayer} from '@deck.gl/layers';
import {createIterable} from '@deck.gl/core';
import {createIterable, log} from '@deck.gl/core';

const defaultProps = {
trailLength: {type: 'number', value: 120, min: 0},
Expand All @@ -31,30 +31,14 @@ export default class TripsLayer extends PathLayer {
getShaders() {
const shaders = super.getShaders();
shaders.inject = {
// Timestamp of the vertex
'vs:#decl': `\
uniform float trailLength;
uniform bool isPath3D;
attribute vec2 instanceTimestamps;
varying float vTime;
`,
// Remove the z component (timestamp) from position
// TODO - Legacy use case, remove in v8
'vec3 nextPosition = mix(instanceEndPositions, instanceRightPositions, isEnd);': `\
vec2 timestamps = instanceTimestamps;
if (!isPath3D) {
prevPosition.z = 0.0;
currPosition.z = 0.0;
nextPosition.z = 0.0;
timestamps.x = instanceStartPositions.z;
timestamps.y = instanceEndPositions.z;
}
`,
// Apply a small shift to battle z-fighting
// Timestamp of the vertex
'vs:#main-end': `\
float shiftZ = sin(timestamps.x) * 1e-4;
gl_Position.z += shiftZ;
vTime = timestamps.x + (timestamps.y - timestamps.x) * vPathPosition.y / vPathLength;
vTime = instanceTimestamps.x + (instanceTimestamps.y - instanceTimestamps.x) * vPathPosition.y / vPathLength;
`,
'fs:#decl': `\
uniform float trailLength;
Expand Down Expand Up @@ -86,13 +70,11 @@ if(vTime > currentTime || vTime < currentTime - trailLength) {
}

draw(params) {
const {trailLength, currentTime, getTimestamps} = this.props;
const {trailLength, currentTime} = this.props;

params.uniforms = Object.assign({}, params.uniforms, {
trailLength,
currentTime,
// TODO - remove in v8
isPath3D: Boolean(getTimestamps)
currentTime
});

super.draw(params);
Expand All @@ -101,13 +83,6 @@ if(vTime > currentTime || vTime < currentTime - trailLength) {
calculateInstanceTimestamps(attribute, {startRow, endRow}) {
const {data, getTimestamps} = this.props;

if (!getTimestamps) {
// TODO - Legacy use case, remove in v8
attribute.constant = true;
attribute.value = new Float32Array(2);
return;
}

const {
pathTesselator: {bufferLayout, instanceCount}
} = this.state;
Expand All @@ -125,6 +100,11 @@ if(vTime > currentTime || vTime < currentTime - trailLength) {

const geometrySize = bufferLayout[objectInfo.index];
const timestamps = getTimestamps(object, objectInfo);

// Support for legacy use case is removed in v8.0
// TODO - remove when all apps are updated
log.assert(timestamps, 'TrisLayer: invalid timestamps');

// For each line segment, we have [startTimestamp, endTimestamp]
for (let j = 0; j < geometrySize; j++) {
value[i++] = timestamps[j];
Expand Down
17 changes: 1 addition & 16 deletions test/modules/geo-layers/trips-layer.spec.js
Expand Up @@ -12,22 +12,7 @@ test('TripsLayer', t => {
getTimestamps: d => d.map(p => p.begin_time)
},
assert: t.ok,
onBeforeUpdate: ({testCase}) => t.comment(testCase.title),
onAfterUpdate: ({layer}) => {
if (layer.props.getTimestamps) {
t.notOk(
layer.getAttributeManager().getAttributes().instanceTimestamps.constant,
'instanceTimestamps populated'
);
t.ok(layer.state.model.program.uniforms.isPath3D, 'uniform isPath3D set');
} else {
t.ok(
layer.getAttributeManager().getAttributes().instanceTimestamps.constant,
'instanceTimestamps ignored'
);
t.notOk(layer.state.model.program.uniforms.isPath3D, 'uniform isPath3D not set');
}
}
onBeforeUpdate: ({testCase}) => t.comment(testCase.title)
});

testLayer({Layer: TripsLayer, testCases, onError: t.notOk});
Expand Down
27 changes: 0 additions & 27 deletions test/render/test-cases.js
Expand Up @@ -1513,33 +1513,6 @@ export const TEST_CASES = [
],
goldenImage: './test/render/golden-images/bitmap.png'
},
{
name: 'trips-layer-2d',
viewState: {
latitude: 37.75,
longitude: -122.45,
zoom: 11.5,
pitch: 0,
bearing: 0
},
layers: [
new TripsLayer({
id: 'trips-2d',
data: dataSamples.trips,
getPath: d => {
const firstPoint = d[0].begin_shape.concat(d[0].begin_time);
const points = d.map(leg => leg.end_shape.concat(leg.end_time));
return [firstPoint].concat(points);
},
getColor: [253, 128, 93],
widthMinPixels: 4,
rounded: true,
trailLength: 500,
currentTime: 500
})
],
goldenImage: './test/render/golden-images/trips.png'
},
{
name: 'trips-layer-3d',
viewState: {
Expand Down

0 comments on commit 89aa08d

Please sign in to comment.