1 | import {Transform, ingest} from 'vega-dataflow';
|
2 | import {inherits, truthy} from 'vega-util';
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | export default function Cross(params) {
|
13 | Transform.call(this, null, params);
|
14 | }
|
15 |
|
16 | Cross.Definition = {
|
17 | 'type': 'Cross',
|
18 | 'metadata': {'generates': true},
|
19 | 'params': [
|
20 | { 'name': 'filter', 'type': 'expr' },
|
21 | { 'name': 'as', 'type': 'string', 'array': true, 'length': 2, 'default': ['a', 'b'] }
|
22 | ]
|
23 | };
|
24 |
|
25 | inherits(Cross, Transform, {
|
26 | transform(_, pulse) {
|
27 | const out = pulse.fork(pulse.NO_SOURCE),
|
28 | as = _.as || ['a', 'b'],
|
29 | a = as[0], b = as[1],
|
30 | reset = !this.value
|
31 | || pulse.changed(pulse.ADD_REM)
|
32 | || _.modified('as')
|
33 | || _.modified('filter');
|
34 |
|
35 | let data = this.value;
|
36 | if (reset) {
|
37 | if (data) out.rem = data;
|
38 | data = pulse.materialize(pulse.SOURCE).source;
|
39 | out.add = this.value = cross(data, a, b, _.filter || truthy);
|
40 | } else {
|
41 | out.mod = data;
|
42 | }
|
43 |
|
44 | out.source = this.value;
|
45 | return out.modifies(as);
|
46 | }
|
47 | });
|
48 |
|
49 | function cross(input, a, b, filter) {
|
50 | var data = [],
|
51 | t = {},
|
52 | n = input.length,
|
53 | i = 0,
|
54 | j, left;
|
55 |
|
56 | for (; i<n; ++i) {
|
57 | t[a] = left = input[i];
|
58 | for (j=0; j<n; ++j) {
|
59 | t[b] = input[j];
|
60 | if (filter(t)) {
|
61 | data.push(ingest(t));
|
62 | t = {};
|
63 | t[a] = left;
|
64 | }
|
65 | }
|
66 | }
|
67 |
|
68 | return data;
|
69 | }
|