Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Sign In

uber / deck.gl / 13779

18 Sep 2019 - 0:00 coverage decreased (-2.9%) to 79.902%
13779

Pull #3623

travis-ci-com

9181eb84f9c35729a3bad740fb7f9d93?size=18&default=identiconweb-flow
beta.2
Pull Request #3623: Bump dependency versions

3405 of 4619 branches covered (73.72%)

Branch coverage included in aggregate %.

7031 of 8442 relevant lines covered (83.29%)

5687.45 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.17
/modules/aggregation-layers/src/gpu-grid-layer/gpu-grid-layer.js
1
// Copyright (c) 2015 - 2017 Uber Technologies, Inc.
14×
2
//
3
// Permission is hereby granted, free of charge, to any person obtaining a copy
4
// of this software and associated documentation files (the "Software"), to deal
5
// in the Software without restriction, including without limitation the rights
6
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
// copies of the Software, and to permit persons to whom the Software is
8
// furnished to do so, subject to the following conditions:
9
//
10
// The above copyright notice and this permission notice shall be included in
11
// all copies or substantial portions of the Software.
12
//
13
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
// THE SOFTWARE.
20

21
import {PhongMaterial} from '@luma.gl/core';
22
import {CompositeLayer, log} from '@deck.gl/core';
23

24
import GPUGridAggregator from '../utils/gpu-grid-aggregation/gpu-grid-aggregator';
25
import {AGGREGATION_OPERATION} from '../utils/aggregation-operation-utils';
26
import {pointToDensityGridData} from '../utils/gpu-grid-aggregation/grid-aggregation-utils';
27
import {defaultColorRange, colorRangeToFlatArray} from '../utils/color-utils';
28
import GPUGridCellLayer from './gpu-grid-cell-layer';
29
import {pointToDensityGridDataCPU} from './../cpu-grid-layer/grid-aggregator';
30

31
const defaultMaterial = new PhongMaterial();
1×
32
const defaultProps = {
1×
33
  // color
34
  colorDomain: null,
35
  colorRange: defaultColorRange,
36
  getColorWeight: {type: 'accessor', value: x => 1},
27×
37
  colorAggregation: 'SUM',
38

39
  // elevation
40
  elevationDomain: null,
41
  elevationRange: [0, 1000],
42
  getElevationWeight: {type: 'accessor', value: x => 1},
27×
43
  elevationAggregation: 'SUM',
44
  elevationScale: {type: 'number', min: 0, value: 1},
45

46
  // grid
47
  cellSize: {type: 'number', min: 0, max: 1000, value: 1000},
48
  coverage: {type: 'number', min: 0, max: 1, value: 1},
UNCOV
49
  getPosition: {type: 'accessor', value: x => x.position},
!
50
  extruded: false,
51
  fp64: false,
52

53
  // Optional material for 'lighting' shader module
54
  material: defaultMaterial,
55

56
  // GPU Aggregation
57
  gpuAggregation: true
58
};
59

60
export default class GPUGridLayer extends CompositeLayer {
61
  initializeState() {
62
    const {gl} = this.context;
3×
63
    const isSupported = GPUGridAggregator.isSupported(gl);
3×
64
    if (!isSupported) {
Branches [[0, 0]] missed. 3×
UNCOV
65
      log.error('GPUGridLayer is not supported on this browser, use GridLayer instead')();
!
66
    }
67
    const options = {
3×
68
      id: `${this.id}-gpu-aggregator`
69
    };
70
    this.state = {
3×
71
      gpuGridAggregator: new GPUGridAggregator(gl, options),
72
      isSupported
73
    };
74
  }
75

76
  updateState(opts) {
77
    const aggregationFlags = this.getAggregationFlags(opts);
15×
78
    if (aggregationFlags) {
15×
79
      // aggregate points into grid cells
80
      this.getLayerData(aggregationFlags);
11×
81
      // reset cached CPU Aggregation results (used for picking)
82
      this.setState({gridHash: null});
11×
83
    }
84
  }
85

86
  finalizeState() {
87
    super.finalizeState();
2×
88
    this.state.gpuGridAggregator.delete();
2×
89
  }
90

91
  getAggregationFlags({oldProps, props, changeFlags}) {
92
    let aggregationFlags = null;
15×
93
    if (!this.state.isSupported) {
Branches [[2, 0]] missed. 15×
94
      // Skip update, layer not supported
UNCOV
95
      return false;
!
96
    }
97
    if (this.isDataChanged({oldProps, props, changeFlags})) {
15×
98
      aggregationFlags = Object.assign({}, aggregationFlags, {dataChanged: true});
10×
99
    }
100
    if (oldProps.cellSize !== props.cellSize) {
15×
101
      aggregationFlags = Object.assign({}, aggregationFlags, {cellSizeChanged: true});
4×
102
    }
103
    return aggregationFlags;
15×
104
  }
105

106
  isDataChanged({oldProps, props, changeFlags}) {
107
    // Flags affecting aggregation data
108
    if (changeFlags.dataChanged) {
15×
109
      return true;
8×
110
    }
111
    if (oldProps.gpuAggregation !== props.gpuAggregation) {
7×
112
      return true;
1×
113
    }
114
    if (
6×
115
      oldProps.colorAggregation !== props.colorAggregation ||
116
      oldProps.elevationAggregation !== props.elevationAggregation
117
    ) {
118
      return true;
1×
119
    }
120
    if (
Branches [[9, 0]] missed. 5×
121
      changeFlags.updateTriggersChanged &&
Branches [[10, 1], [10, 2], [10, 3], [10, 4]] missed.
122
      (changeFlags.updateTriggersChanged.all ||
123
        changeFlags.updateTriggersChanged.getPosition ||
124
        changeFlags.updateTriggersChanged.getColorWeight ||
125
        changeFlags.updateTriggersChanged.getElevationWeight)
126
    ) {
UNCOV
127
      return true;
!
128
    }
129
    return false;
5×
130
  }
131

132
  getHashKeyForIndex(index) {
UNCOV
133
    const {gridSize, gridOrigin, cellSize} = this.state;
!
UNCOV
134
    const yIndex = Math.floor(index / gridSize[0]);
!
UNCOV
135
    const xIndex = index - yIndex * gridSize[0];
!
136
    // This will match the index to the hash-key to access aggregation data from CPU aggregation results.
UNCOV
137
    const latIdx = Math.floor(
!
138
      (yIndex * cellSize[1] + gridOrigin[1] + 90 + cellSize[1] / 2) / cellSize[1]
139
    );
UNCOV
140
    const lonIdx = Math.floor(
!
141
      (xIndex * cellSize[0] + gridOrigin[0] + 180 + cellSize[0] / 2) / cellSize[0]
142
    );
UNCOV
143
    return `${latIdx}-${lonIdx}`;
!
144
  }
145

146
  getPositionForIndex(index) {
147
    const {gridSize, gridOrigin, cellSize} = this.state;
!
UNCOV
148
    const yIndex = Math.floor(index / gridSize[0]);
!
UNCOV
149
    const xIndex = index - yIndex * gridSize[0];
!
UNCOV
150
    const yPos = yIndex * cellSize[1] + gridOrigin[1];
!
UNCOV
151
    const xPos = xIndex * cellSize[0] + gridOrigin[0];
!
UNCOV
152
    return [xPos, yPos];
!
153
  }
154

155
  getPickingInfo({info, mode}) {
UNCOV
156
    const {index} = info;
!
UNCOV
157
    let object = null;
!
UNCOV
158
    if (index >= 0) {
Branches [[11, 0], [11, 1]] missed. !
UNCOV
159
      const {gpuGridAggregator} = this.state;
!
UNCOV
160
      const position = this.getPositionForIndex(index);
!
UNCOV
161
      const colorInfo = GPUGridAggregator.getAggregationData(
!
162
        Object.assign({pixelIndex: index}, gpuGridAggregator.getData('color'))
163
      );
UNCOV
164
      const elevationInfo = GPUGridAggregator.getAggregationData(
!
165
        Object.assign({pixelIndex: index}, gpuGridAggregator.getData('elevation'))
166
      );
167

168
      object = {
!
169
        colorValue: colorInfo.cellWeight,
170
        elevationValue: elevationInfo.cellWeight,
171
        count: colorInfo.cellCount || elevationInfo.cellCount,
Branches [[12, 0], [12, 1]] missed.
172
        position,
173
        totalCount: colorInfo.totalCount || elevationInfo.totalCount
Branches [[13, 0], [13, 1]] missed.
174
      };
UNCOV
175
      if (mode !== 'hover') {
Branches [[14, 0], [14, 1]] missed. !
176
        // perform CPU aggregation for full list of points for each cell
177
        const {data, getPosition} = this.props;
!
178
        let {gridHash} = this.state;
!
179
        if (!gridHash) {
Branches [[15, 0], [15, 1]] missed. !
180
          const cpuAggregation = pointToDensityGridDataCPU(data, this.props.cellSize, getPosition);
!
181
          gridHash = cpuAggregation.gridHash;
!
182
          this.setState({gridHash});
!
183
        }
184
        const key = this.getHashKeyForIndex(index);
!
185
        const cpuAggregationData = gridHash[key];
!
186
        Object.assign(object, cpuAggregationData);
!
187
      }
188
    }
189

190
    return Object.assign(info, {
!
191
      picked: Boolean(object),
192
      // override object with picked cell
193
      object
194
    });
195
  }
196

197
  getLayerData(aggregationFlags) {
198
    const {
199
      data,
200
      cellSize: cellSizeMeters,
201
      getPosition,
202
      gpuAggregation,
203
      getColorWeight,
204
      colorAggregation,
205
      getElevationWeight,
206
      elevationAggregation,
207
      fp64
208
    } = this.props;
11×
209
    const weightParams = {
11×
210
      color: {
211
        getWeight: getColorWeight,
212
        operation:
213
          AGGREGATION_OPERATION[colorAggregation] ||
214
          AGGREGATION_OPERATION[defaultProps.colorAggregation],
215
        needMin: true,
216
        needMax: true,
217
        combineMaxMin: true
218
      },
219
      elevation: {
220
        getWeight: getElevationWeight,
221
        operation:
222
          AGGREGATION_OPERATION[elevationAggregation] ||
Branches [[17, 1]] missed.
223
          AGGREGATION_OPERATION[defaultProps.elevationAggregation],
224
        needMin: true,
225
        needMax: true,
226
        combineMaxMin: true
227
      }
228
    };
229
    const {weights, gridSize, gridOrigin, cellSize, boundingBox} = pointToDensityGridData({
11×
230
      data,
231
      cellSizeMeters,
232
      getPosition,
233
      weightParams,
234
      gpuAggregation,
235
      gpuGridAggregator: this.state.gpuGridAggregator,
236
      boundingBox: this.state.boundingBox, // avoid parsing data when it is not changed.
237
      aggregationFlags,
238
      fp64
239
    });
240
    this.setState({weights, gridSize, gridOrigin, cellSize, boundingBox});
11×
241
  }
242

243
  renderLayers() {
244
    if (!this.state.isSupported) {
Branches [[18, 0]] missed. 16×
245
      return null;
!
246
    }
247
    const {
248
      elevationScale,
249
      extruded,
250
      cellSize: cellSizeMeters,
251
      coverage,
252
      material,
253
      elevationRange,
254
      colorDomain,
255
      elevationDomain
256
    } = this.props;
16×
257

258
    const {weights, gridSize, gridOrigin, cellSize} = this.state;
16×
259

260
    const colorRange = colorRangeToFlatArray(this.props.colorRange);
16×
261

262
    const SubLayerClass = this.getSubLayerClass('gpu-grid-cell', GPUGridCellLayer);
16×
263

264
    return new SubLayerClass(
16×
265
      {
266
        gridSize,
267
        gridOrigin,
268
        gridOffset: cellSize,
269
        colorRange,
270
        elevationRange,
271
        colorDomain,
272
        elevationDomain,
273

274
        cellSize: cellSizeMeters,
275
        coverage,
276
        material,
277
        elevationScale,
278
        extruded
279
      },
280
      this.getSubLayerProps({
281
        id: 'gpu-grid-cell'
282
      }),
283
      {
284
        data: weights,
285
        numInstances: gridSize[0] * gridSize[1]
286
      }
287
    );
288
  }
289
}
290

291
GPUGridLayer.layerName = 'GPUGridLayer';
1×
292
GPUGridLayer.defaultProps = defaultProps;
1×
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
BLOG · TWITTER · Legal & Privacy · Supported CI Services · What's a CI service? · Automated Testing

© 2019 Coveralls, LLC