mascot-vis 2.1.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +4 -3
  2. package/dist/mascot-es.js +27745 -0
  3. package/dist/mascot-min.js +186 -199
  4. package/dist/mascot-umd.js +27781 -0
  5. package/js/depGraphVis.js +66 -0
  6. package/package.json +23 -15
  7. package/src-new-ts/action/createElement.ts +91 -0
  8. package/src-new-ts/action/encode.js +20 -0
  9. package/src-new-ts/action/repeat.js +128 -0
  10. package/src-new-ts/action/traverseScene.js +41 -0
  11. package/src-new-ts/data/Network.js +2 -0
  12. package/src-new-ts/data/Scope.js +135 -0
  13. package/src-new-ts/data/Table.js +263 -0
  14. package/src-new-ts/data/Tree.js +3 -0
  15. package/src-new-ts/data/field.ts +115 -0
  16. package/src-new-ts/data/import.ts +96 -0
  17. package/src-new-ts/data/predicate.ts +82 -0
  18. package/src-new-ts/depgraph/DepGraph.js +178 -0
  19. package/src-new-ts/depgraph/Edge.js +9 -0
  20. package/src-new-ts/depgraph/SceneGraph2DepGraph.js +110 -0
  21. package/src-new-ts/depgraph/Signal.js +12 -0
  22. package/src-new-ts/depgraph/operator/BoundsEvaluator.js +30 -0
  23. package/src-new-ts/depgraph/operator/Dataflow.js +41 -0
  24. package/src-new-ts/depgraph/operator/DomainBuilder.js +50 -0
  25. package/src-new-ts/depgraph/updateDepGraph.js +45 -0
  26. package/src-new-ts/depgraph/variable/BoundsVar.js +81 -0
  27. package/src-new-ts/depgraph/variable/ChannelVar.js +17 -0
  28. package/src-new-ts/depgraph/variable/DataScopeVar.js +12 -0
  29. package/src-new-ts/depgraph/variable/DomainVar.js +15 -0
  30. package/src-new-ts/depgraph/variable/FieldVar.js +17 -0
  31. package/src-new-ts/depgraph/variable/LayoutParameter.js +8 -0
  32. package/src-new-ts/depgraph/variable/ScaleVar.js +13 -0
  33. package/src-new-ts/depgraph/variable/Variable.js +39 -0
  34. package/src-new-ts/element/gradient/LinearGradient.js +37 -0
  35. package/src-new-ts/element/group/Collection.js +109 -0
  36. package/src-new-ts/element/group/Group.js +307 -0
  37. package/src-new-ts/element/group/Scene.js +98 -0
  38. package/src-new-ts/element/mark/CircleMark.ts +85 -0
  39. package/src-new-ts/element/mark/Mark.ts +233 -0
  40. package/src-new-ts/element/mark/PathMark.js +483 -0
  41. package/src-new-ts/element/mark/Segment.js +29 -0
  42. package/src-new-ts/element/mark/Vertex.js +118 -0
  43. package/src-new-ts/encode/Scale.ts +115 -0
  44. package/src-new-ts/index.ts +19 -0
  45. package/src-new-ts/layout/Layout.ts +3 -0
  46. package/src-new-ts/render/CanvasRenderer.ts +24 -0
  47. package/src-new-ts/render/SVGRenderer.js +316 -0
  48. package/src-new-ts/util.ts +3 -0
  49. package/src-old/action/Classify.js +53 -0
  50. package/src-old/action/Densify.js +199 -0
  51. package/src-old/action/Partition.js +531 -0
  52. package/src-old/action/Repeat.js +106 -0
  53. package/src-old/action/Repopulate.js +44 -0
  54. package/src-old/action/Stratify.js +156 -0
  55. package/src-old/basic/Gradient.js +37 -0
  56. package/src-old/basic/Point.js +51 -0
  57. package/src-old/basic/Rectangle.js +63 -0
  58. package/src-old/bind/bindToAngle.js +56 -0
  59. package/src-old/bind/bindToAreaMark.js +360 -0
  60. package/src-old/bind/bindToColor.js +114 -0
  61. package/src-old/bind/bindToLink.js +81 -0
  62. package/src-old/bind/bindToPosition.js +283 -0
  63. package/src-old/bind/bindToRadialDistance.js +62 -0
  64. package/src-old/bind/bindToSize.js +235 -0
  65. package/src-old/bind/bindToText.js +60 -0
  66. package/src-old/bind/bindToThickness.js +100 -0
  67. package/src-old/constraint/AffixConstraint.js +129 -0
  68. package/src-old/constraint/AlignConstraint.js +58 -0
  69. package/src-old/core/Encoding.js +336 -0
  70. package/src-old/core/Scale.js +322 -0
  71. package/src-old/core/SceneLoader.js +290 -0
  72. package/src-old/core/SceneValidator.js +232 -0
  73. package/src-old/core/SpecExecutor.js +113 -0
  74. package/src-old/core/SpecGenerator.js +350 -0
  75. package/src-old/data/DataImporter.js +64 -0
  76. package/src-old/data/DataScope.js +124 -0
  77. package/src-old/data/DataTable.js +338 -0
  78. package/src-old/data/Network.js +106 -0
  79. package/src-old/data/Tree.js +251 -0
  80. package/src-old/data/transform/Bin.js +46 -0
  81. package/src-old/data/transform/Filter.js +48 -0
  82. package/src-old/data/transform/Groupby.js +18 -0
  83. package/src-old/data/transform/KDE.js +58 -0
  84. package/src-old/data/transform/Sort.js +14 -0
  85. package/src-old/data/transform/Split.js +5 -0
  86. package/src-old/data/transform/partition.js +46 -0
  87. package/src-old/history/UndoRedoStack +0 -0
  88. package/src-old/index.js +271 -0
  89. package/src-old/indexSVG.js +259 -0
  90. package/src-old/interaction/Interaction.js +91 -0
  91. package/src-old/interaction/MouseEvent.js +8 -0
  92. package/src-old/interaction/Selection.js +9 -0
  93. package/src-old/interaction/brush.js +362 -0
  94. package/src-old/item/Segment.js +29 -0
  95. package/src-old/item/Vertex.js +118 -0
  96. package/src-old/item/composite/Collection.js +106 -0
  97. package/src-old/item/composite/Glyph.js +19 -0
  98. package/src-old/item/composite/Group.js +310 -0
  99. package/src-old/item/composite/Scene.js +1251 -0
  100. package/src-old/item/mark/ArcPath.js +181 -0
  101. package/src-old/item/mark/AreaPath.js +78 -0
  102. package/src-old/item/mark/CirclePath.js +102 -0
  103. package/src-old/item/mark/EllipsePath.js +5 -0
  104. package/src-old/item/mark/Image.js +101 -0
  105. package/src-old/item/mark/LinkPath.js +118 -0
  106. package/src-old/item/mark/Mark.js +163 -0
  107. package/src-old/item/mark/Path.js +494 -0
  108. package/src-old/item/mark/PointText.js +201 -0
  109. package/src-old/item/mark/PolygonPath.js +64 -0
  110. package/src-old/item/mark/RectPath.js +88 -0
  111. package/src-old/item/mark/RingPath.js +92 -0
  112. package/src-old/item/refs/Axis.js +362 -0
  113. package/src-old/item/refs/EncodingAxis.js +515 -0
  114. package/src-old/item/refs/Gridlines.js +144 -0
  115. package/src-old/item/refs/LayoutAxis.js +316 -0
  116. package/src-old/item/refs/Legend.js +273 -0
  117. package/src-old/layout/Circular.js +95 -0
  118. package/src-old/layout/Force.js +52 -0
  119. package/src-old/layout/Grid.js +423 -0
  120. package/src-old/layout/Layout.js +13 -0
  121. package/src-old/layout/Packing.js +56 -0
  122. package/src-old/layout/Stack.js +264 -0
  123. package/src-old/layout/Strata.js +88 -0
  124. package/src-old/layout/Sugiyama.js +59 -0
  125. package/src-old/layout/TidyTree.js +105 -0
  126. package/src-old/layout/Treemap.js +87 -0
  127. package/src-old/renderer/SVGInteractionHandler.js +241 -0
  128. package/src-old/renderer/SVGRenderer.js +325 -0
  129. package/src-old/renderer/WebGLRenderer.js +1097 -0
  130. package/src-old/renderer/WebGLRenderer2.js +249 -0
  131. package/src-old/renderer/threejs/Line2.js +18 -0
  132. package/src-old/renderer/threejs/LineGeometry.js +77 -0
  133. package/src-old/renderer/threejs/LineMaterial.js +605 -0
  134. package/src-old/renderer/threejs/LineSegments2.js +281 -0
  135. package/src-old/renderer/threejs/LineSegmentsGeometry.js +226 -0
  136. package/src-old/renderer/threejs/Wireframe.js +51 -0
  137. package/src-old/renderer/threejs/WireframeGeometry2.js +16 -0
  138. package/src-old/scale/areaSize.js +0 -0
  139. package/src-old/scale/domain.js +38 -0
  140. package/src-old/util/Constants.js +180 -0
  141. package/src-old/util/DataUtil.js +35 -0
  142. package/src-old/util/ItemUtil.js +586 -0
  143. package/src-old/util/Numerical.js +33 -0
  144. package/tests/demo-tests/README.md +80 -0
  145. package/tests/demo-tests/SVG2PNG.js +56 -0
  146. package/tests/demo-tests/demos2CanvasPNGs.js +69 -0
  147. package/tests/demo-tests/demos2ScenesSVGs.js +100 -0
  148. package/tests/demo-tests/pathElementWorker.js +91 -0
  149. package/tests/demo-tests/pixelTest.js +62 -0
  150. package/tests/demo-tests/renderDemos.html +132 -0
  151. package/tests/demo-tests/serializationTest.js +36 -0
  152. package/tests/demo-tests/serializeDemos.html +134 -0
  153. package/tests/unit-tests/README.md +4 -0
  154. package/tests/unit-tests/jasmine-browser.json +21 -0
  155. package/tests/unit-tests/jasmine.json +14 -0
  156. package/tests/unit-tests/testSpec.js +274 -0
  157. package/dist/mascot.js +0 -24920
  158. package/interactive.html +0 -592
@@ -0,0 +1,39 @@
1
+ import { generateUniqueID } from "../../util.js";
2
+
3
+ export default class Variable {
4
+ constructor(type) {
5
+ this._id = "v_" + generateUniqueID();
6
+ this._type = type;
7
+ this._incomings = [];
8
+ this._outgoings = [];
9
+ this._undirected = [];
10
+ }
11
+
12
+ get id() {
13
+ return this._id;
14
+ }
15
+
16
+ get incomingEdges() {
17
+ return this._incomings;
18
+ }
19
+
20
+ get outgoingEdges() {
21
+ return this._outgoings;
22
+ }
23
+
24
+ get undirectedEdges() {
25
+ return this._undirected;
26
+ }
27
+
28
+ get type() {
29
+ return this._type;
30
+ }
31
+ }
32
+
33
+ export const VarType = Object.freeze({
34
+ CHANNEL: 'channel',
35
+ DATASCOPE: 'datascope',
36
+ DOMAIN: 'domain',
37
+ BOUNDS: 'bounds',
38
+ FIELD: 'field'
39
+ });
@@ -0,0 +1,37 @@
1
+ import { generateUniqueID } from "../../util.js";
2
+ import { ElementType } from "../../action/createElement.js";
3
+
4
+ export default class LinearGradient {
5
+
6
+ constructor(params) {
7
+ let args = params ? params : {};
8
+ this._stops = [];
9
+ this.type = ElementType.LinearGradient;
10
+ this.id = this.type + generateUniqueID();
11
+ this.x1 = ("x1" in args) ? args.x1 : 0;
12
+ this.x2 = ("x2" in args) ? args.x2 : 100;
13
+ this.y1 = ("y1" in args) ? args.y1 : 0;
14
+ this.y2 = ("y2" in args) ? args.y2 : 0;
15
+ }
16
+
17
+ toJSON() {
18
+ let json = {};
19
+ json.type = this.type;
20
+ json.id = this.id;
21
+ json.x1 = this.x1;
22
+ json.x2 = this.x2;
23
+ json.y1 = this.y1;
24
+ json.y2 = this.y2;
25
+ json.stops = this._stops;
26
+ return json;
27
+ }
28
+
29
+ addStop(offset, color, opacity) {
30
+ this._stops.push({ offset: offset, color: color, opacity: opacity });
31
+ }
32
+
33
+ get stops() {
34
+ return this._stops;
35
+ }
36
+
37
+ }
@@ -0,0 +1,109 @@
1
+ import { ElementType } from "../../action/createElement.js";
2
+ import { MSCRowID } from "../../data/Table.js";
3
+ import { FieldType } from "../../data/field.js";
4
+ import { CanvasProvider } from "../../render/CanvasRenderer.js";
5
+ import { generateUniqueID } from "../../util.js";
6
+ import Group from "./Group.js";
7
+
8
+ export default class Collection extends Group {
9
+
10
+ constructor() {
11
+ super();
12
+ this._type = ElementType.Collection;
13
+ this._id = this.type + generateUniqueID();
14
+ this._classId = this.id;
15
+ this._childrenOrder = undefined;
16
+ }
17
+
18
+ get childrenOrder() {
19
+ if (!this._childrenOrder)
20
+ return { "field": MSCRowID, "direction": "asc" };
21
+ else
22
+ return this._childrenOrder;
23
+ }
24
+
25
+ set childrenOrder(o) {
26
+ if (!("field" in o) && !("direction" in o)) return;
27
+ let field = o.field;
28
+ if (!this.dataScope.dataTable.hasField(field)) {
29
+ console.warn("Cannot order collection children by an non-existent field", o.field);
30
+ return;
31
+ }
32
+ this._childrenOrder = o;
33
+ let f;
34
+ if (field === MSCRowID) {
35
+ f = (a, b) => parseInt(a.dataScope.getFieldValue(field).substring(1)) - parseInt(b.dataScope.getFieldValue(field).substring(1));
36
+ } else {
37
+ let type = this.children[0].dataScope.getFieldType(field);
38
+ switch (type) {
39
+ case FieldType.Date:
40
+ break;
41
+ case FieldType.Number:
42
+ case FieldType.Integer:
43
+ f = (a, b) => a.dataScope.aggregateNumericalField(field) - b.dataScope.aggregateNumericalField(field);
44
+ break;
45
+ case FieldType.String:
46
+ if (o.ranking)
47
+ f = (a, b) => o.ranking.indexOf(a.dataScope.getFieldValue(field)) - o.ranking.indexOf(b.dataScope.getFieldValue(field));
48
+ else
49
+ f = (a, b) => (a.dataScope.getFieldValue(field) < b.dataScope.getFieldValue(field) ? -1 : 1);
50
+ break;
51
+ }
52
+ }
53
+ this.children.sort(f);
54
+
55
+ if (o.direction == "desc")
56
+ this.children.reverse();
57
+ if (this.layout)
58
+ this.layout.run();
59
+ }
60
+
61
+ duplicate() {
62
+ let coll = this.getScene().collection();
63
+ for (let i = 0; i < this.children.length; i++) {
64
+ let c = this.children[i];
65
+ coll.addChild(c.duplicate());
66
+ }
67
+ coll.classId = this.classId;
68
+ this.parent.addChild(coll);
69
+ if (this._layout) {
70
+ let layout = this._layout.clone();
71
+ coll.layout = layout;
72
+ }
73
+ return coll;
74
+ }
75
+
76
+ contains(x, y) {
77
+ let irregular2Ds = [ElementType.Arc, ElementType.Pie, ElementType.Polygon, ElementType.Area];
78
+ if (irregular2Ds.indexOf(this.firstChild.type) >= 0) {
79
+ let svgData = this.getSVGPathData();
80
+ if (svgData !== "") {
81
+ let ctx = CanvasProvider.getContext(),
82
+ p = new Path2D(svgData);
83
+ ctx.lineWidth = Math.max(this.strokeWidth, 2.5);
84
+ ctx.stroke(p);
85
+ return ctx.isPointInPath(p, x, y);
86
+ }
87
+ }
88
+ if (!this._bounds) {
89
+ this._updateBounds();
90
+ }
91
+ return this._bounds.contains(x, y);
92
+ }
93
+
94
+ getSVGPathData() {
95
+ let d = "";
96
+ for (let i of this.children) {
97
+ if (i.getSVGPathData)
98
+ d += i.getSVGPathData();
99
+ else if (i.bounds) {
100
+ let b = i.bounds;
101
+ d += ["M", b.left, b.top].join(" ");
102
+ d += ["L", b.right, b.top].join(" ");
103
+ d += ["L", b.right, b.bottom].join(" ");
104
+ d += ["L", b.left, b.bottom, "Z"].join(" ");
105
+ }
106
+ }
107
+ return d;
108
+ }
109
+ }
@@ -0,0 +1,307 @@
1
+ /**
2
+ * Same as group in graphical design tools
3
+ **/
4
+
5
+ import { generateUniqueID } from "../../util.js";
6
+ import { ElementType } from "../../action/createElement.js";
7
+
8
+ export default class Group {
9
+
10
+ constructor() {
11
+ this._children = [];
12
+ this._dataScope = undefined;
13
+ this._layout = undefined;
14
+ this._type = ElementType.Group;
15
+ this._id = this.type + generateUniqueID();
16
+ }
17
+
18
+ get id() {
19
+ return this._id;
20
+ }
21
+
22
+ get type() {
23
+ return this._type;
24
+ }
25
+
26
+ // set id(id) {
27
+ // if (this.type === ElementType.Scene || !this.getScene())
28
+ // this._id = id;
29
+ // else {
30
+ // delete this.getScene()._itemMap[this._id];
31
+ // this._id = id;
32
+ // this.getScene()._itemMap[id] = this;
33
+ // }
34
+ // }
35
+
36
+ contains(x, y) {
37
+ if (!this._bounds) {
38
+ this._updateBounds();
39
+ }
40
+ return this._bounds.contains(x, y);
41
+ }
42
+
43
+ toJSON() {
44
+ let json = {};
45
+ json.type = this.type;
46
+ json.id = this.id;
47
+ if (this._dataScope)
48
+ json.dataScope = this._dataScope.toJSON();
49
+ if (this.classId)
50
+ json.classId = this.classId;
51
+ if (this._layout)
52
+ json.layout = this._layout.toJSON();
53
+ if (this._bounds)
54
+ json.bounds = this._bounds.toJSON();
55
+ json.children = [];
56
+ if (this.children.length > 0) { //&& this.type != ItemType.Axis
57
+ for (let c of this.children) {
58
+ json.children.push(c.toJSON());
59
+ }
60
+ }
61
+ if (this.childrenOrder) {
62
+ json.childrenOrder = this.childrenOrder;
63
+ }
64
+ return json;
65
+ }
66
+
67
+ get children() {
68
+ return this._children;
69
+ }
70
+
71
+ addChild(c) {
72
+ if (this.children.indexOf(c) >= 0) return;
73
+ if (c.parent)
74
+ c.parent.removeChild(c);
75
+ this.children.push(c);
76
+ c.parent = this;
77
+ }
78
+
79
+ addChildAt(c,index){
80
+ if (c.parent)
81
+ c.parent.removeChild(c);
82
+ this.children.splice(index, 0, c);
83
+ c.parent = this;
84
+ }
85
+
86
+ removeChild(c) {
87
+ let idx = this.children.indexOf(c);
88
+ if (idx >= 0) {
89
+ this.children.splice(idx, 1);
90
+ c.parent = null;
91
+ }
92
+ }
93
+
94
+ removeChildAt(i) {
95
+ this.children[i].parent = null;
96
+ this.children.splice(i, 1);
97
+ }
98
+
99
+ removeAll() {
100
+ for (let c of this.children)
101
+ c.parent = null;
102
+ this.children = [];
103
+ }
104
+
105
+ get dataScope() {
106
+ return this._dataScope;
107
+ }
108
+
109
+ set dataScope(ds) {
110
+ this._dataScope = ds;
111
+ if (ds === undefined) {
112
+ for (let c of this.children) {
113
+ c.dataScope = ds;
114
+ }
115
+ } else {
116
+ for (let c of this.children) {
117
+ if (c.dataScope)
118
+ c.dataScope = c.dataScope.merge(ds);
119
+ else
120
+ c.dataScope = ds;
121
+ }
122
+ }
123
+ }
124
+
125
+ // _doTranslate(dx, dy) {
126
+ // for (let child of this.children) {
127
+ // child._doTranslate(dx, dy);
128
+ // }
129
+ // this._updateBounds();
130
+ // if (this._layout) {
131
+ // if (this._layout._left !== undefined)
132
+ // this._layout._left += dx;
133
+ // if (this._layout._top !== undefined)
134
+ // this._layout._top += dy;
135
+ // if (this._layout.x !== undefined)
136
+ // this._layout.x += dx;
137
+ // if (this._layout.y !== undefined)
138
+ // this._layout.y += dy;
139
+ // //this._layout.run();
140
+ // }
141
+ // this._updateBounds();
142
+ // }
143
+
144
+ getInternalEncodings(channel) {
145
+ if (this.children.length == 0)
146
+ return [];
147
+ let item = this.children[0], scene = this.getScene();
148
+ let encodingKeys = Object.keys(scene.encodings);
149
+ let classIds = [];
150
+ while(item) {
151
+ if (item.classId && classIds.indexOf(item.classId) < 0)
152
+ classIds.push(item.classId);
153
+ if (item.type === ElementType.Glyph) {
154
+ item.children.forEach(d => classIds.push(d.classId));
155
+ break;
156
+ } else if (item.children) {
157
+ item = item.children[0];
158
+ } else
159
+ break;
160
+ }
161
+ let result = [];
162
+ for (let k of encodingKeys) {
163
+ let tokens = k.split("_");
164
+ for (let classId of classIds) {
165
+ if (tokens[0] == classId) {
166
+ if (scene.encodings[k][channel])
167
+ result.push(scene.encodings[k][channel]);
168
+ }
169
+ }
170
+ }
171
+ return result;
172
+ }
173
+
174
+ get firstChild() {
175
+ return this.children[0];
176
+ }
177
+
178
+ get lastChild() {
179
+ return this.children[this.children.length - 1];
180
+ }
181
+
182
+ set layout(l) {
183
+ this._layout = l;
184
+ if (l) {
185
+ l.group = this;
186
+ this._layout.run();
187
+ } else {
188
+ //check if there are position encodings and reapply them
189
+ let xEncs = this.getInternalEncodings("x"),
190
+ yEncs = this.getInternalEncodings("y");
191
+ for (let e of xEncs) {
192
+ e._map();
193
+ e._apply();
194
+ }
195
+ for (let e of yEncs) {
196
+ e._map();
197
+ e._apply();
198
+ }
199
+ }
200
+ }
201
+
202
+ get layout() {
203
+ return this._layout;
204
+ }
205
+
206
+ // get bounds() {
207
+ // if (!this._bounds) {
208
+ // this._updateBounds();
209
+ // }
210
+ // return this._bounds;
211
+ // }
212
+
213
+ // get refBounds() {
214
+ // let cRefBounds = this.children.map (d => d.refBounds);
215
+ // let left = Math.min(...cRefBounds.map(d => d.left)), top = Math.min(...cRefBounds.map(d => d.top)),
216
+ // right = Math.max(...cRefBounds.map(d => d.right)), bottom = Math.max(...cRefBounds.map(d => d.bottom));
217
+ // return new Rectangle(left, top, right - left, bottom - top);
218
+ // }
219
+
220
+ get x() {
221
+ return this.bounds.x;
222
+ }
223
+
224
+ get y() {
225
+ return this.bounds.y;
226
+ }
227
+
228
+ // _updateBounds() {
229
+ // if (this.children.length > 0){
230
+ // this._bounds = this.children[0].bounds.clone();
231
+ // for (let i = 1; i < this.children.length; i++) {
232
+ // if (this.children[i].visibility == "hidden")
233
+ // continue;
234
+ // this._bounds = this._bounds.union(this.children[i].bounds);
235
+ // }
236
+ // if (this._layout && this._layout.type == "grid") {
237
+ // let cellBounds = this._layout.cellBounds;
238
+ // for (let i = 0; i < cellBounds.length; i++) {
239
+ // this._bounds = this._bounds.union(cellBounds[i]);
240
+ // }
241
+ // }
242
+ // } else {
243
+ // this._bounds = new Rectangle(0, 0, 0, 0);
244
+ // }
245
+ // }
246
+
247
+ // sortChildrenByData(field, reverse, order) {
248
+ // let type = this.children[0].dataScope.getFieldType(field);
249
+ // let f;
250
+ // switch (type) {
251
+ // case DataType.Date:
252
+ // break;
253
+ // case DataType.Number:
254
+ // case DataType.Integer:
255
+ // f = (a, b) => a.dataScope.aggregateNumericalField(field) - b.dataScope.aggregateNumericalField(field);
256
+ // break;
257
+ // case DataType.String:
258
+ // if (order)
259
+ // f = (a, b) => order.indexOf(a.dataScope.getFieldValue(field)) - order.indexOf(b.dataScope.getFieldValue(field));
260
+ // else
261
+ // f = (a, b) => (a.dataScope.getFieldValue(field) < b.dataScope.getFieldValue(field) ? -1 : 1 );
262
+ // break;
263
+ // }
264
+ // this.children.sort(f);
265
+ // if (reverse)
266
+ // this.children.reverse();
267
+ // if (this.layout)
268
+ // this.layout.run();
269
+ // this._childrenOrder = {field: field, direction: reverse ? "desc" : "asc", ranking: order};
270
+ // }
271
+
272
+ // sortChildren(channel, reverse){
273
+ // let f;
274
+ // switch (channel){
275
+ // case "x":
276
+ // case "y":
277
+ // case "width":
278
+ // case "height":
279
+ // f = (a, b) => a.bounds[channel] - b.bounds[channel];
280
+ // break;
281
+ // default:
282
+ // f = (a, b) => a[channel] - b[channel];
283
+ // break;
284
+ // }
285
+ // this.children.sort(f);
286
+ // if (reverse)
287
+ // this.children.reverse();
288
+ // if (this.layout)
289
+ // this.layout.run();
290
+ // this.childrenOrder = {channel: channel, reverse: reverse};
291
+ // }
292
+
293
+ set visibility(v) {
294
+ if (v == "hidden")
295
+ this._visibility = v;
296
+ else
297
+ this._visibility = "visible";
298
+ for (let c of this.children)
299
+ c.visibility = v;
300
+ }
301
+
302
+ get visibility() {
303
+ if (!this._visibility)
304
+ return "visible";
305
+ return this._visibility;
306
+ }
307
+ }
@@ -0,0 +1,98 @@
1
+ import { ElementType, PrimitiveMark } from "../../action/createElement.js";
2
+ import Group from "./Group.js";
3
+ import { generateUniqueID } from "../../util.js";
4
+ import DependencyGraph from "../../depgraph/DepGraph.js";
5
+ import { encodingSpecified, newMarkCreated } from "../../depgraph/updateDepGraph.js";
6
+ import { VarType } from "../../depgraph/variable/Variable.js";
7
+ import DataTable, { MSCRowID } from "../../data/Table.js";
8
+ import { repeatElement, validateRepeatArguments } from "../../action/repeat.js";
9
+ import Tree from "../../data/Tree.js";
10
+ import Network from "../../data/Network.js";
11
+ import { createMark } from "../../action/createElement.js";
12
+ import { getPeers } from "../../action/traverseScene.js";
13
+ import { validateEncodeArguments } from "../../action/encode.js";
14
+ import { createScale } from "../../encode/Scale.js";
15
+
16
+ export default class Scene extends Group {
17
+
18
+ constructor(args) {
19
+ super();
20
+ this._itemMap = {};
21
+ this._type = ElementType.Scene;
22
+ this._id = this._type + generateUniqueID();
23
+ if (args && args.fillColor) {
24
+ this.fillColor = args.fillColor;
25
+ }
26
+ this._encodings = {};
27
+ this._depGraph = new DependencyGraph();
28
+ }
29
+
30
+ get depGraph() {
31
+ return this._depGraph;
32
+ }
33
+
34
+ mark(type, param) {
35
+ if (Object.values(PrimitiveMark).indexOf(type) < 0)
36
+ throw new Error("Mascot does not allow directly creating a " + type);
37
+ let args = param === undefined ? {} : param;
38
+ args.type = type;
39
+ let m = createMark(args);
40
+ if (m !== null) {
41
+ m._classId = m.id;
42
+ this.addChild(m);
43
+ this._itemMap[m.id] = m;
44
+ newMarkCreated(m, this._depGraph);
45
+ }
46
+ return m;
47
+ }
48
+
49
+ repeat(elem, data, param) {
50
+ param["field"] = param["field"] || MSCRowID;
51
+ validateRepeatArguments(elem, data, param);
52
+
53
+ if (data instanceof Tree || data instanceof Network) {
54
+ throw "Not implemented";
55
+ // return repeatNodeLink(this, elem[0], elem[1], data);
56
+ } else if (data instanceof DataTable) {
57
+ let collection = repeatElement(this, elem, param["field"], data);
58
+ // console.log(this._depGraph);
59
+ if (param.layout)
60
+ collection.layout = param.layout;
61
+ return collection;
62
+ }
63
+ }
64
+
65
+ //example usage in the scatterplot demo: scn.encode(circle, { field: "GDP per capita", channel: "x" });
66
+ encode(elem, param) {
67
+ //TODO: complete the validateEncodeArguments function in action/encode.js to validate the arguments
68
+ validateEncodeArguments(elem, param);
69
+ let scale = param.scale ? param.scale : createScale(param.field, param.channel, elem),
70
+ aggregator = param.aggregator ? param.aggregator : "sum";
71
+ encodingSpecified(param.field, param.channel, elem, scale, aggregator, this._depGraph);
72
+ }
73
+
74
+
75
+ /**
76
+ *
77
+ * @param {*} varType: type of variable: channel, field, bounds, datascope, scale, ...
78
+ * @param {*} newVal: variable value: "x", "y", "radius", etc. for channel, ...
79
+ * @param {*} compnt: the component that the variable belongs to, e.g., channel/bounds/datascope: element, field: dataset
80
+ */
81
+ onChange(varType, ...params) {
82
+ if (Object.values(VarType).indexOf(varType) < 0)
83
+ throw new Error('Unknown Variable Type: ' + varType);
84
+ this._depGraph.processChange(varType, ...params);
85
+ }
86
+
87
+ setChannels(root, params) {
88
+ this.setProperties(params, root);
89
+ getPeers(root).map(elem => this.setProperties(params, elem));
90
+ this.onChange('channel', ...Object.keys(params), root);
91
+ }
92
+
93
+ setProperties(params, c) {
94
+ for (const [key, value] of Object.entries(params)) {
95
+ if ('_' + key in c) c['_' + key] = value;
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,85 @@
1
+ import Mark from "./Mark";
2
+
3
+ // Define an interface for constructor arguments
4
+ interface CircleMarkArgs {
5
+ x?: number;
6
+ y?: number;
7
+ radius?: number;
8
+ [key: string]: any; // This allows for additional properties not explicitly defined here
9
+ }
10
+
11
+ export default class CircleMark extends Mark {
12
+ private _x: number;
13
+ private _y: number;
14
+ private _radius: number;
15
+
16
+ constructor(args: CircleMarkArgs) {
17
+ super(args);
18
+ this._x = args.x ?? 0; // Use nullish coalescing operator
19
+ this._y = args.y ?? 0;
20
+ this._radius = args.radius ?? 100;
21
+ }
22
+
23
+ // Define setters and getters with types
24
+ set strokeColor(c: string) {
25
+
26
+ }
27
+
28
+ set radius(r: number) {
29
+ this._radius = r;
30
+ }
31
+
32
+ get strokeColor(): string {
33
+ return this.styles.strokeColor;
34
+ }
35
+
36
+ get strokeDash(): string {
37
+ return this.styles.strokeDash;
38
+ }
39
+
40
+ get fillColor(): string {
41
+ return this.styles.fillColor;
42
+ }
43
+
44
+ get strokeWidth(): number {
45
+ return this.styles.strokeWidth;
46
+ }
47
+
48
+ get x(): number {
49
+ return this._x;
50
+ }
51
+
52
+ get y(): number {
53
+ return this._y;
54
+ }
55
+
56
+ get radius(): number {
57
+ return this._radius;
58
+ }
59
+
60
+ get area(): number {
61
+ return Math.PI * Math.pow(this._radius, 2);
62
+ }
63
+
64
+ copyPropertiesTo(target: CircleMark): void {
65
+ super.copyPropertiesTo(target);
66
+ target._x = this._x;
67
+ target._y = this._y;
68
+ target._radius = this._radius;
69
+ }
70
+
71
+ getSVGPathData(): string {
72
+ return [
73
+ "M", this._x, this._y,
74
+ "m", -this._radius, "0",
75
+ "a", this._radius, this._radius, "0 1,0", this._radius * 2, "0",
76
+ "a", this._radius, this._radius, "0 1,0", -(this._radius * 2), "0"
77
+ ].join(" ");
78
+ }
79
+
80
+ contains(px: number, py: number): boolean {
81
+
82
+ const dist = Math.sqrt(Math.pow(px - this.x, 2) + Math.pow(py - this.y, 2));
83
+ return dist <= this.radius + this.strokeWidth;
84
+ }
85
+ }