• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

visgl / deck.gl / 10519844544

23 Aug 2024 04:24AM UTC coverage: 88.902% (-0.2%) from 89.141%
10519844544

push

github

web-flow
GPU Aggregation (6/8): HexagonLayer (#9098)

6667 of 7306 branches covered (91.25%)

Branch coverage included in aggregate %.

674 of 710 new or added lines in 5 files covered. (94.93%)

223 existing lines in 3 files now uncovered.

55786 of 62943 relevant lines covered (88.63%)

6459.83 hits per line

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

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

1✔
21
import {
1✔
22
  CompositeLayer,
1✔
23
  AttributeManager,
1✔
24
  LayerDataSource,
1✔
25
  _compareProps as compareProps,
1✔
26
  UpdateParameters,
1✔
27
  CompositeLayerProps,
1✔
28
  Attribute
1✔
29
} from '@deck.gl/core';
1✔
30
import {filterProps} from './utils/prop-utils';
1✔
31

1✔
32
export type AggregationLayerProps<DataT> = CompositeLayerProps & {
1✔
33
  data: LayerDataSource<DataT>;
1✔
34
};
1✔
35

1✔
36
export default abstract class AggregationLayer<
1✔
37
  DataT,
1✔
38
  ExtraPropsT extends {} = {}
1✔
39
> extends CompositeLayer<Required<AggregationLayer<DataT>> & ExtraPropsT> {
1✔
40
  static layerName = 'AggregationLayer';
1✔
41

1✔
42
  state!: {
1✔
43
    ignoreProps?: Record<string, any>;
1✔
44
    dimensions?: any;
1✔
45
    changedAttributes?: Record<string, any>;
1✔
46
  };
1✔
47

1✔
48
  initializeAggregationLayer(dimensions: any) {
1✔
49
    super.initializeState(this.context);
1✔
50

1✔
51
    this.setState({
1✔
52
      // Layer props , when changed doesn't require updating aggregation
1✔
53
      ignoreProps: filterProps((this.constructor as any)._propTypes, dimensions.data.props),
1✔
54
      dimensions
1✔
55
    });
1✔
56
  }
1✔
57

1✔
58
  updateState(opts: UpdateParameters<this>) {
1✔
59
    super.updateState(opts);
5✔
60
    const {changeFlags} = opts;
5✔
61
    if (changeFlags.extensionsChanged) {
5✔
62
      const shaders = this.getShaders({});
2✔
63
      if (shaders && shaders.defines) {
2✔
64
        shaders.defines.NON_INSTANCED_MODEL = 1;
1✔
65
      }
1✔
66
      this.updateShaders(shaders);
2✔
67
    }
2✔
68

5✔
69
    // Explictly call to update attributes as 'CompositeLayer' doesn't call this
5✔
70
    this._updateAttributes();
5✔
71
  }
5✔
72

1✔
73
  updateAttributes(changedAttributes) {
1✔
74
    // Super classes, can refer to state.changedAttributes to determine what
10✔
75
    // attributes changed
10✔
76
    this.setState({changedAttributes});
10✔
77
  }
10✔
78

1✔
79
  getAttributes(): {[id: string]: Attribute} {
1✔
UNCOV
80
    return this.getAttributeManager()!.getAttributes();
×
UNCOV
81
  }
×
82

1✔
83
  getModuleSettings() {
1✔
84
    // For regular layer draw this happens during draw cycle (_drawLayersInViewport) not during update cycle
×
85
    // For aggregation layers this is called during updateState to update aggregation data
×
86
    // NOTE: it is similar to LayerPass._getModuleParameters() but doesn't inlcude `effects` it is not needed for aggregation
×
87
    const {viewport, mousePosition, device} = this.context;
×
88
    const moduleSettings = Object.assign(Object.create(this.props), {
×
89
      viewport,
×
90
      mousePosition,
×
91
      picking: {
×
92
        isActive: 0
×
93
      },
×
94
      // @ts-expect-error TODO - assuming WebGL context
×
95
      devicePixelRatio: device.canvasContext.cssToDeviceRatio()
×
96
    });
×
97
    return moduleSettings;
×
98
  }
×
99

1✔
100
  updateShaders(shaders) {
1✔
UNCOV
101
    // Default implemention is empty, subclasses can update their Model objects if needed
×
UNCOV
102
  }
×
103

1✔
104
  /**
1✔
105
   * Checks if aggregation is dirty
1✔
106
   * @param {Object} updateOpts - object {props, oldProps, changeFlags}
1✔
107
   * @param {Object} params - object {dimension, compareAll}
1✔
108
   * @param {Object} params.dimension - {props, accessors} array of props and/or accessors
1✔
109
   * @param {Boolean} params.compareAll - when `true` it will include non layer props for comparision
1✔
110
   * @returns {Boolean} - returns true if dimensions' prop or accessor is changed
1✔
111
   **/
1✔
112
  isAggregationDirty(
1✔
113
    updateOpts,
5✔
114
    params: {compareAll?: boolean; dimension?: any} = {}
5✔
115
  ): string | boolean {
5✔
116
    const {props, oldProps, changeFlags} = updateOpts;
5✔
117
    const {compareAll = false, dimension} = params;
5✔
118
    const {ignoreProps} = this.state;
5✔
119
    const {props: dataProps, accessors = []} = dimension;
5✔
120
    const {updateTriggersChanged} = changeFlags;
5✔
121
    if (changeFlags.dataChanged) {
5✔
122
      return true;
1✔
123
    }
1✔
124
    if (updateTriggersChanged) {
5✔
125
      if (updateTriggersChanged.all) {
1!
126
        return true;
×
127
      }
×
128
      for (const accessor of accessors) {
1!
129
        if (updateTriggersChanged[accessor]) {
×
130
          return true;
×
131
        }
×
132
      }
×
133
    }
1✔
134
    if (compareAll) {
4✔
135
      if (changeFlags.extensionsChanged) {
4✔
136
        return true;
1✔
137
      }
1✔
138
      // Compare non layer props too (like extension props)
3✔
139
      // ignoreprops refers to all Layer props other than aggregation props that need to be comapred
3✔
140
      return compareProps({
3✔
141
        oldProps,
3✔
142
        newProps: props,
3✔
143
        ignoreProps,
3✔
144
        propTypes: (this.constructor as any)._propTypes
3✔
145
      });
3✔
146
    }
3!
147
    // Compare props of the dimension
×
148
    for (const name of dataProps) {
×
149
      if (props[name] !== oldProps[name]) {
×
150
        return true;
×
151
      }
×
152
    }
×
153
    return false;
×
154
  }
5✔
155

1✔
156
  /**
1✔
157
   * Checks if an attribute is changed
1✔
158
   * @param {String} name - name of the attribute
1✔
159
   * @returns {Boolean} - `true` if attribute `name` is changed, `false` otherwise,
1✔
160
   *                       If `name` is not passed or `undefiend`, `true` if any attribute is changed, `false` otherwise
1✔
161
   **/
1✔
162
  isAttributeChanged(name?: string) {
1✔
163
    const {changedAttributes} = this.state;
10✔
164
    if (!name) {
10✔
165
      // if name not specified return true if any attribute is changed
5✔
166
      return !isObjectEmpty(changedAttributes);
5✔
167
    }
5✔
168
    return changedAttributes && changedAttributes[name] !== undefined;
5✔
169
  }
10✔
170

1✔
171
  // Private
1✔
172

1✔
173
  // override Composite layer private method to create AttributeManager instance
1✔
174
  _getAttributeManager() {
1✔
175
    return new AttributeManager(this.context.device, {
1✔
176
      id: this.props.id,
1✔
177
      stats: this.context.stats
1✔
178
    });
1✔
179
  }
1✔
180
}
1✔
181

1✔
182
// Helper methods
1✔
183

1✔
184
// Returns true if given object is empty, false otherwise.
1✔
185
function isObjectEmpty(obj) {
5✔
186
  let isEmpty = true;
5✔
187
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
5✔
188
  for (const key in obj) {
5✔
189
    isEmpty = false;
2✔
190
    break;
2✔
191
  }
2✔
192
  return isEmpty;
5✔
193
}
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc