mascot-vis 3.0.0 → 3.0.2
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.
- package/dist/mascot-esm.js +186 -0
- package/package.json +3 -6
- package/dist/mascot-es.js +0 -27745
- package/dist/mascot-min.js +0 -186
- package/dist/mascot-umd.js +0 -27781
- package/js/depGraphVis.js +0 -66
- package/src-new-ts/action/createElement.ts +0 -91
- package/src-new-ts/action/encode.js +0 -20
- package/src-new-ts/action/repeat.js +0 -128
- package/src-new-ts/action/traverseScene.js +0 -41
- package/src-new-ts/data/Network.js +0 -2
- package/src-new-ts/data/Scope.js +0 -135
- package/src-new-ts/data/Table.js +0 -263
- package/src-new-ts/data/Tree.js +0 -3
- package/src-new-ts/data/field.ts +0 -115
- package/src-new-ts/data/import.ts +0 -96
- package/src-new-ts/data/predicate.ts +0 -82
- package/src-new-ts/depgraph/DepGraph.js +0 -178
- package/src-new-ts/depgraph/Edge.js +0 -9
- package/src-new-ts/depgraph/SceneGraph2DepGraph.js +0 -110
- package/src-new-ts/depgraph/Signal.js +0 -12
- package/src-new-ts/depgraph/operator/BoundsEvaluator.js +0 -30
- package/src-new-ts/depgraph/operator/Dataflow.js +0 -41
- package/src-new-ts/depgraph/operator/DomainBuilder.js +0 -50
- package/src-new-ts/depgraph/updateDepGraph.js +0 -45
- package/src-new-ts/depgraph/variable/BoundsVar.js +0 -81
- package/src-new-ts/depgraph/variable/ChannelVar.js +0 -17
- package/src-new-ts/depgraph/variable/DataScopeVar.js +0 -12
- package/src-new-ts/depgraph/variable/DomainVar.js +0 -15
- package/src-new-ts/depgraph/variable/FieldVar.js +0 -17
- package/src-new-ts/depgraph/variable/LayoutParameter.js +0 -8
- package/src-new-ts/depgraph/variable/ScaleVar.js +0 -13
- package/src-new-ts/depgraph/variable/Variable.js +0 -39
- package/src-new-ts/element/gradient/LinearGradient.js +0 -37
- package/src-new-ts/element/group/Collection.js +0 -109
- package/src-new-ts/element/group/Group.js +0 -307
- package/src-new-ts/element/group/Scene.js +0 -98
- package/src-new-ts/element/mark/CircleMark.ts +0 -85
- package/src-new-ts/element/mark/Mark.ts +0 -233
- package/src-new-ts/element/mark/PathMark.js +0 -483
- package/src-new-ts/element/mark/Segment.js +0 -29
- package/src-new-ts/element/mark/Vertex.js +0 -118
- package/src-new-ts/encode/Scale.ts +0 -115
- package/src-new-ts/index.ts +0 -19
- package/src-new-ts/layout/Layout.ts +0 -3
- package/src-new-ts/render/CanvasRenderer.ts +0 -24
- package/src-new-ts/render/SVGRenderer.js +0 -316
- package/src-new-ts/util.ts +0 -3
- package/src-old/action/Classify.js +0 -53
- package/src-old/action/Densify.js +0 -199
- package/src-old/action/Partition.js +0 -531
- package/src-old/action/Repeat.js +0 -106
- package/src-old/action/Repopulate.js +0 -44
- package/src-old/action/Stratify.js +0 -156
- package/src-old/basic/Gradient.js +0 -37
- package/src-old/basic/Point.js +0 -51
- package/src-old/basic/Rectangle.js +0 -63
- package/src-old/bind/bindToAngle.js +0 -56
- package/src-old/bind/bindToAreaMark.js +0 -360
- package/src-old/bind/bindToColor.js +0 -114
- package/src-old/bind/bindToLink.js +0 -81
- package/src-old/bind/bindToPosition.js +0 -283
- package/src-old/bind/bindToRadialDistance.js +0 -62
- package/src-old/bind/bindToSize.js +0 -235
- package/src-old/bind/bindToText.js +0 -60
- package/src-old/bind/bindToThickness.js +0 -100
- package/src-old/constraint/AffixConstraint.js +0 -129
- package/src-old/constraint/AlignConstraint.js +0 -58
- package/src-old/core/Encoding.js +0 -336
- package/src-old/core/Scale.js +0 -322
- package/src-old/core/SceneLoader.js +0 -290
- package/src-old/core/SceneValidator.js +0 -232
- package/src-old/core/SpecExecutor.js +0 -113
- package/src-old/core/SpecGenerator.js +0 -350
- package/src-old/data/DataImporter.js +0 -64
- package/src-old/data/DataScope.js +0 -124
- package/src-old/data/DataTable.js +0 -338
- package/src-old/data/Network.js +0 -106
- package/src-old/data/Tree.js +0 -251
- package/src-old/data/transform/Bin.js +0 -46
- package/src-old/data/transform/Filter.js +0 -48
- package/src-old/data/transform/Groupby.js +0 -18
- package/src-old/data/transform/KDE.js +0 -58
- package/src-old/data/transform/Sort.js +0 -14
- package/src-old/data/transform/Split.js +0 -5
- package/src-old/data/transform/partition.js +0 -46
- package/src-old/history/UndoRedoStack +0 -0
- package/src-old/index.js +0 -271
- package/src-old/indexSVG.js +0 -259
- package/src-old/interaction/Interaction.js +0 -91
- package/src-old/interaction/MouseEvent.js +0 -8
- package/src-old/interaction/Selection.js +0 -9
- package/src-old/interaction/brush.js +0 -362
- package/src-old/item/Segment.js +0 -29
- package/src-old/item/Vertex.js +0 -118
- package/src-old/item/composite/Collection.js +0 -106
- package/src-old/item/composite/Glyph.js +0 -19
- package/src-old/item/composite/Group.js +0 -310
- package/src-old/item/composite/Scene.js +0 -1251
- package/src-old/item/mark/ArcPath.js +0 -181
- package/src-old/item/mark/AreaPath.js +0 -78
- package/src-old/item/mark/CirclePath.js +0 -102
- package/src-old/item/mark/EllipsePath.js +0 -5
- package/src-old/item/mark/Image.js +0 -101
- package/src-old/item/mark/LinkPath.js +0 -118
- package/src-old/item/mark/Mark.js +0 -163
- package/src-old/item/mark/Path.js +0 -494
- package/src-old/item/mark/PointText.js +0 -201
- package/src-old/item/mark/PolygonPath.js +0 -64
- package/src-old/item/mark/RectPath.js +0 -88
- package/src-old/item/mark/RingPath.js +0 -92
- package/src-old/item/refs/Axis.js +0 -362
- package/src-old/item/refs/EncodingAxis.js +0 -515
- package/src-old/item/refs/Gridlines.js +0 -144
- package/src-old/item/refs/LayoutAxis.js +0 -316
- package/src-old/item/refs/Legend.js +0 -273
- package/src-old/layout/Circular.js +0 -95
- package/src-old/layout/Force.js +0 -52
- package/src-old/layout/Grid.js +0 -423
- package/src-old/layout/Layout.js +0 -13
- package/src-old/layout/Packing.js +0 -56
- package/src-old/layout/Stack.js +0 -264
- package/src-old/layout/Strata.js +0 -88
- package/src-old/layout/Sugiyama.js +0 -59
- package/src-old/layout/TidyTree.js +0 -105
- package/src-old/layout/Treemap.js +0 -87
- package/src-old/renderer/SVGInteractionHandler.js +0 -241
- package/src-old/renderer/SVGRenderer.js +0 -325
- package/src-old/renderer/WebGLRenderer.js +0 -1097
- package/src-old/renderer/WebGLRenderer2.js +0 -249
- package/src-old/renderer/threejs/Line2.js +0 -18
- package/src-old/renderer/threejs/LineGeometry.js +0 -77
- package/src-old/renderer/threejs/LineMaterial.js +0 -605
- package/src-old/renderer/threejs/LineSegments2.js +0 -281
- package/src-old/renderer/threejs/LineSegmentsGeometry.js +0 -226
- package/src-old/renderer/threejs/Wireframe.js +0 -51
- package/src-old/renderer/threejs/WireframeGeometry2.js +0 -16
- package/src-old/scale/areaSize.js +0 -0
- package/src-old/scale/domain.js +0 -38
- package/src-old/util/Constants.js +0 -180
- package/src-old/util/DataUtil.js +0 -35
- package/src-old/util/ItemUtil.js +0 -586
- package/src-old/util/Numerical.js +0 -33
- package/tests/demo-tests/README.md +0 -80
- package/tests/demo-tests/SVG2PNG.js +0 -56
- package/tests/demo-tests/demos2CanvasPNGs.js +0 -69
- package/tests/demo-tests/demos2ScenesSVGs.js +0 -100
- package/tests/demo-tests/pathElementWorker.js +0 -91
- package/tests/demo-tests/pixelTest.js +0 -62
- package/tests/demo-tests/renderDemos.html +0 -132
- package/tests/demo-tests/serializationTest.js +0 -36
- package/tests/demo-tests/serializeDemos.html +0 -134
- package/tests/unit-tests/README.md +0 -4
- package/tests/unit-tests/jasmine-browser.json +0 -21
- package/tests/unit-tests/jasmine.json +0 -14
- package/tests/unit-tests/testSpec.js +0 -274
package/src-old/util/ItemUtil.js
DELETED
|
@@ -1,586 +0,0 @@
|
|
|
1
|
-
import Path from "../item/mark/Path";
|
|
2
|
-
import {ItemType, Alignment, LayoutType} from "./Constants";
|
|
3
|
-
import Mark from "../item/mark/Mark";
|
|
4
|
-
import GridLayout from "../layout/Grid";
|
|
5
|
-
import PackingLayout from "../layout/Packing";
|
|
6
|
-
import TreemapLayout from "../layout/Treemap";
|
|
7
|
-
import StackLayout from "../layout/Stack";
|
|
8
|
-
import TidyTreeLayout from "../layout/TidyTree";
|
|
9
|
-
import ForceLayout from "../layout/Force";
|
|
10
|
-
import SugiyamaLayout from "../layout/Sugiyama";
|
|
11
|
-
import StrataLayout from "../layout/Strata";
|
|
12
|
-
|
|
13
|
-
export function evaluatePredicate(itm, p) {
|
|
14
|
-
if ("field" in p) {
|
|
15
|
-
if (!itm.dataScope) return false;
|
|
16
|
-
let f = p["field"];
|
|
17
|
-
if ("value" in p) {
|
|
18
|
-
return itm.dataScope.getFieldValue(f) === p["value"];
|
|
19
|
-
} else if ("interval" in p) {
|
|
20
|
-
let v = itm.dataScope.getFieldValue(f);
|
|
21
|
-
return v >= p["interval"][0] && v <= p["interval"][1];
|
|
22
|
-
} else if ("values" in p) {
|
|
23
|
-
return p["values"].indexOf(itm.dataScope.getFieldValue(f)) >= 0;
|
|
24
|
-
} else {
|
|
25
|
-
return itm.dataScope.hasField(f);
|
|
26
|
-
}
|
|
27
|
-
} else if ("channel" in p) {
|
|
28
|
-
let c = p["channel"];
|
|
29
|
-
if ("value" in p) {
|
|
30
|
-
return itm[c] === p["value"];
|
|
31
|
-
} else if ("interval" in p) {
|
|
32
|
-
return itm[c] >= p["interval"][0] && itm[c] <= p["interval"][1];
|
|
33
|
-
} else if ("values" in p) {
|
|
34
|
-
return p["values"].indexOf(itm[c]) >= 0;
|
|
35
|
-
}
|
|
36
|
-
} else if ("type" in p) {
|
|
37
|
-
return itm.type === p["type"];
|
|
38
|
-
} else if ("id" in p) {
|
|
39
|
-
return itm.id === p["id"];
|
|
40
|
-
} else if ("classId" in p) {
|
|
41
|
-
return itm.classId === p["classId"];
|
|
42
|
-
} else if ("fields" in p) {
|
|
43
|
-
if (!itm.dataScope) return false;
|
|
44
|
-
let f1 = p["fields"][0], f2 = p["fields"][1],
|
|
45
|
-
v1 = itm.dataScope.getFieldValue(f1), v2 = itm.dataScope.getFieldValue(f2);
|
|
46
|
-
switch (p["operator"]) {
|
|
47
|
-
case "==":
|
|
48
|
-
return v1 == v2;
|
|
49
|
-
case ">":
|
|
50
|
-
return v1 > v2;
|
|
51
|
-
case ">=":
|
|
52
|
-
return v1 >= v2;
|
|
53
|
-
case "<":
|
|
54
|
-
return v1 < v2;
|
|
55
|
-
case "<=":
|
|
56
|
-
return v1 <= v2;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function findItems(container, predicates) {
|
|
63
|
-
let result = [];
|
|
64
|
-
_findItemsRecursive(container, predicates, result);
|
|
65
|
-
return result;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function _findItemsRecursive(itm, predicates, result) {
|
|
69
|
-
if (!itm) return;
|
|
70
|
-
if (itm.type == "axis" || itm.type == "legend" || itm.type == "gridlines") return;
|
|
71
|
-
if (_matchCriteria(itm, predicates)) {
|
|
72
|
-
result.push(itm);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (itm.vertices){
|
|
76
|
-
for (let i of itm.vertices.concat(itm.segments)) {
|
|
77
|
-
if (_matchCriteria(i, predicates))
|
|
78
|
-
result.push(i);
|
|
79
|
-
}
|
|
80
|
-
} else if (itm.children && itm.children.length > 0) {
|
|
81
|
-
for (let c of itm.children)
|
|
82
|
-
_findItemsRecursive(c, predicates, result);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function _matchCriteria(cpnt, predicates) {
|
|
87
|
-
for (let p of predicates) {
|
|
88
|
-
if (!evaluatePredicate(cpnt, p))
|
|
89
|
-
return false;
|
|
90
|
-
}
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function getPeers(item, scene) {
|
|
95
|
-
if (item.type == "vertex") {
|
|
96
|
-
return _getPeerVertices(item, scene);
|
|
97
|
-
} else if (item.type == "segment") {
|
|
98
|
-
return _getPeerSegments(item, scene);
|
|
99
|
-
} else {
|
|
100
|
-
// return item.classId ? findItems(scene, d => d.classId == item.classId) : [];
|
|
101
|
-
return item.classId ? findItems(scene, [{"classId": item.classId}]) : [];
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
//returns an array of peer arrays, peers within each array have the same parent
|
|
106
|
-
export function getPeersGroupedByParent(item, scene) {
|
|
107
|
-
let result = {}, peers = getPeers(item, scene);
|
|
108
|
-
for (let p of peers) {
|
|
109
|
-
let parent = p.parent.id;
|
|
110
|
-
if (!(parent in result))
|
|
111
|
-
result[parent] = [];
|
|
112
|
-
result[parent].push(p);
|
|
113
|
-
}
|
|
114
|
-
return Object.keys(result).map(d => result[d]);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function _getPeerSegments(segment, container) {
|
|
118
|
-
if (segment.dataScope) {
|
|
119
|
-
let parent = segment.parent;
|
|
120
|
-
if (!parent) throw new Error("segment has no parent mark");
|
|
121
|
-
let parentPeers = findItems(container, [{"classId": parent.classId}]);
|
|
122
|
-
let results = [];
|
|
123
|
-
for (let p of parentPeers) {
|
|
124
|
-
results = results.concat(p.segments);
|
|
125
|
-
}
|
|
126
|
-
return results;
|
|
127
|
-
} else {
|
|
128
|
-
let parent = segment.parent;
|
|
129
|
-
if (!parent) throw new Error("segment has no parent mark");
|
|
130
|
-
let index = parent.segments.indexOf(segment);
|
|
131
|
-
let parentPeers = findItems(container, [{"classId": parent.classId}]);
|
|
132
|
-
let results = [];
|
|
133
|
-
for (let p of parentPeers) {
|
|
134
|
-
results.push(p.segments[index]);
|
|
135
|
-
}
|
|
136
|
-
return results;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function _getPeerVertices(vertex, container) {
|
|
141
|
-
if (vertex.classId) { //for node-link diagrams
|
|
142
|
-
|
|
143
|
-
} else if (vertex.dataScope) {
|
|
144
|
-
let parent = vertex.parent;
|
|
145
|
-
if (!parent) throw new Error("vertex has no parent mark");
|
|
146
|
-
let parentPeers = findItems(container, [{"classId": parent.classId}]);
|
|
147
|
-
let results = [];
|
|
148
|
-
if (parent.type === ItemType.Area) {
|
|
149
|
-
let idx = parent.vertices.indexOf(vertex), firstHalf = idx < parent.vertices.length/2;
|
|
150
|
-
for (let p of parentPeers) {
|
|
151
|
-
let vertices = firstHalf ? p.vertices.slice(0, p.vertices.length/2) : p.vertices.slice(p.vertices.length/2);
|
|
152
|
-
results = results.concat(vertices.filter(d => d.dataScope));
|
|
153
|
-
}
|
|
154
|
-
} else {
|
|
155
|
-
for (let p of parentPeers) {
|
|
156
|
-
results = results.concat(p.vertices.filter(d => d.dataScope));
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return results;
|
|
160
|
-
} else {
|
|
161
|
-
let parent = vertex.parent;
|
|
162
|
-
if (!parent) throw new Error("vertex has no parent mark");
|
|
163
|
-
let index = parent.vertices.indexOf(vertex);
|
|
164
|
-
let parentPeers = findItems(container, [{"classId": parent.classId}]);
|
|
165
|
-
let results = [];
|
|
166
|
-
for (let p of parentPeers) {
|
|
167
|
-
results.push(p.vertices[index]);
|
|
168
|
-
}
|
|
169
|
-
return results;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function getClosestLayout(item, type) {
|
|
174
|
-
let parent = item.parent;
|
|
175
|
-
while (parent && parent.type != ItemType.Scene) {
|
|
176
|
-
if (parent.layout) {
|
|
177
|
-
if ( (!type) || (type && parent.layout.type === type))
|
|
178
|
-
return parent.layout;
|
|
179
|
-
}
|
|
180
|
-
parent = parent.parent;
|
|
181
|
-
}
|
|
182
|
-
return undefined;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// export function isInGlyph(item) {
|
|
186
|
-
// let parent = item.parent;
|
|
187
|
-
// while (parent && parent.type != ItemType.Scene) {
|
|
188
|
-
// if (parent.type === ItemType.Glyph)
|
|
189
|
-
// return true;
|
|
190
|
-
// parent = parent.parent;
|
|
191
|
-
// }
|
|
192
|
-
// return false;
|
|
193
|
-
// }
|
|
194
|
-
|
|
195
|
-
export function getAllLayouts(items) { // get all layouts in a bottom-up manner
|
|
196
|
-
let parents = getParents(items), allLayouts = [];
|
|
197
|
-
while (parents && parents[0].type != ItemType.Scene) {
|
|
198
|
-
for (let parent of parents) {
|
|
199
|
-
if (parent.layout) {
|
|
200
|
-
allLayouts.push(parent.layout);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
parents = getParents(parents);
|
|
204
|
-
}
|
|
205
|
-
return allLayouts;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export function getCellBoundsInLayout(item) {
|
|
209
|
-
let itm = item, parent = item.parent;
|
|
210
|
-
while (parent && parent.type != ItemType.Scene) {
|
|
211
|
-
if (parent.layout){
|
|
212
|
-
let idx = parent.children.findIndex(d => d == itm);
|
|
213
|
-
return parent.layout.cellBounds[idx];
|
|
214
|
-
}
|
|
215
|
-
itm = itm.parent;
|
|
216
|
-
parent = itm.parent;
|
|
217
|
-
}
|
|
218
|
-
return undefined;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export function getCellIndexInLayout(item) {
|
|
222
|
-
let itm = item, parent = item.parent;
|
|
223
|
-
while (parent && parent.type != ItemType.Scene) {
|
|
224
|
-
if (parent.layout){
|
|
225
|
-
return parent.children.findIndex(d => d == itm);
|
|
226
|
-
}
|
|
227
|
-
itm = itm.parent;
|
|
228
|
-
parent = itm.parent;
|
|
229
|
-
}
|
|
230
|
-
return undefined;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
export function getCellBoundsInGridLayout(item) {
|
|
234
|
-
let itm = item, parent = item.parent;
|
|
235
|
-
while (parent && parent.type != ItemType.Scene) {
|
|
236
|
-
if (parent.layout && parent.layout.type == LayoutType.Grid){
|
|
237
|
-
let idx = parent.children.findIndex(d => d == itm);
|
|
238
|
-
return parent.layout.cellBounds[idx];
|
|
239
|
-
}
|
|
240
|
-
itm = itm.parent;
|
|
241
|
-
parent = itm.parent;
|
|
242
|
-
}
|
|
243
|
-
return undefined;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
export function getTopLevelLayout(item, type) {
|
|
247
|
-
let parent = item.parent, layout = undefined;
|
|
248
|
-
while (parent && parent.type !== ItemType.Scene) {
|
|
249
|
-
if (parent.layout)
|
|
250
|
-
if ( (!type) || (type && parent.layout.type === type))
|
|
251
|
-
layout = parent.layout;
|
|
252
|
-
parent = parent.parent;
|
|
253
|
-
}
|
|
254
|
-
return layout;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export function getEncodingKey(item) {
|
|
258
|
-
if (item.classId) {
|
|
259
|
-
return item.classId;
|
|
260
|
-
} else if (item.type == "vertex" && item.dataScope) { //vertex created from densify
|
|
261
|
-
if (item.parent.type === ItemType.Area) {
|
|
262
|
-
let firstHalf = item.parent.vertices.indexOf(item) < item.parent.vertices.length/2;
|
|
263
|
-
return item.parent.classId + "_v_" + (firstHalf ? 0 : item.parent.vertices.length-1) ;
|
|
264
|
-
}
|
|
265
|
-
else
|
|
266
|
-
return item.parent.classId + "_v";
|
|
267
|
-
} else if (item.type == "vertex") { //vertex with index
|
|
268
|
-
return item.parent.classId + "_v_" + item.parent.vertices.indexOf(item);
|
|
269
|
-
} else if (item.type == "segment" && item.dataScope) { //segment created from densify
|
|
270
|
-
return item.parent.classId + "_s";
|
|
271
|
-
} else if (item.type == "segment") { //segment with index
|
|
272
|
-
return item.parent.classId + "_s_" + item.parent.segments.indexOf(item);
|
|
273
|
-
} else {
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
export function sameClass(item1, item2) {
|
|
279
|
-
return getEncodingKey(item1).split("_")[0] === getEncodingKey(item2).split("_")[0];
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
export function getParents(items) {
|
|
283
|
-
let result = [];
|
|
284
|
-
for (let p of items) {
|
|
285
|
-
if (p.parent && result.indexOf(p.parent) < 0)
|
|
286
|
-
result.push(p.parent);
|
|
287
|
-
}
|
|
288
|
-
return result;
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
export function getAllChildren(cpnt) {
|
|
292
|
-
let result = [];
|
|
293
|
-
if (cpnt.children && cpnt.children.length > 0) {
|
|
294
|
-
for (let c of cpnt.children) {
|
|
295
|
-
result.push(c);
|
|
296
|
-
result = result.concat(getAllChildren(c));
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
return result;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
export function getLeafMarks(cpnt) {
|
|
303
|
-
let result = [];
|
|
304
|
-
if (isMark(cpnt)) {
|
|
305
|
-
result.push(cpnt);
|
|
306
|
-
} else if (cpnt.children && cpnt.children.length > 0 && !isGuide(cpnt)) {
|
|
307
|
-
for (let c of cpnt.children) {
|
|
308
|
-
result = result.concat(getLeafMarks(c));
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
return result;
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
export function getLeafItems(cpnt) {
|
|
315
|
-
let result = [];
|
|
316
|
-
if (cpnt.children && cpnt.children.length > 0) {
|
|
317
|
-
for (let c of cpnt.children) {
|
|
318
|
-
result = result.concat(getLeafItems(c));
|
|
319
|
-
}
|
|
320
|
-
} else {
|
|
321
|
-
result.push(cpnt);
|
|
322
|
-
}
|
|
323
|
-
return result;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
export function isGuide(item) {
|
|
327
|
-
return item.type === ItemType.Axis || item.type === ItemType.Legend || item.type === ItemType.Gridlines;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
export function isMark(cmpnt) {
|
|
331
|
-
return cmpnt instanceof Mark;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export function isPath(cmpnt) {
|
|
335
|
-
return cmpnt instanceof Path;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
export function isPartOfLegend(cmpnt) {
|
|
339
|
-
let itm = cmpnt;
|
|
340
|
-
while (itm.parent) {
|
|
341
|
-
itm = itm.parent;
|
|
342
|
-
if (itm.type == ItemType.Legend)
|
|
343
|
-
return true;
|
|
344
|
-
}
|
|
345
|
-
return false;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
export function itemIsRepeatable(itm) {
|
|
349
|
-
// if (!itm.dataScope)
|
|
350
|
-
// return true;
|
|
351
|
-
// else if (itm)
|
|
352
|
-
// return itm.dataScope.numTuples.length > 1;
|
|
353
|
-
if ((isMark(itm) || itm.type == ItemType.Glyph) && !itm.dataScope)
|
|
354
|
-
return true;
|
|
355
|
-
else if (itm.type === ItemType.Collection)
|
|
356
|
-
return itm.firstChild.dataScope.numTuples > 1;
|
|
357
|
-
|
|
358
|
-
return false;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
export const ItemCounter = {
|
|
362
|
-
"area" : 0,
|
|
363
|
-
"rect" : 0,
|
|
364
|
-
"circle": 0,
|
|
365
|
-
"pie": 0,
|
|
366
|
-
"line": 0,
|
|
367
|
-
"path" : 0,
|
|
368
|
-
"ring" : 0,
|
|
369
|
-
"arc": 0,
|
|
370
|
-
"image": 0,
|
|
371
|
-
"pointText": 0,
|
|
372
|
-
"collection": 0,
|
|
373
|
-
"group": 0,
|
|
374
|
-
"scene": 0,
|
|
375
|
-
"axis": 0,
|
|
376
|
-
"glyph": 0,
|
|
377
|
-
"legend": 0,
|
|
378
|
-
"polygon": 0,
|
|
379
|
-
"gridlines": 0,
|
|
380
|
-
"LinearGradient": 0,
|
|
381
|
-
"link": 0,
|
|
382
|
-
"scale": 0,
|
|
383
|
-
"datatable": 0
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
export function canAlign(items, direction, scene){
|
|
387
|
-
if (direction == Alignment.Top || direction == Alignment.Bottom || direction == Alignment.Middle) {
|
|
388
|
-
for (let item of items) {
|
|
389
|
-
if (!canMoveVertically(item, scene))
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
return true;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
if (direction == Alignment.Left || direction == Alignment.Right || direction == Alignment.Center) {
|
|
396
|
-
for (let item of items) {
|
|
397
|
-
if (!canMoveHorizontally(item, scene))
|
|
398
|
-
return false;
|
|
399
|
-
}
|
|
400
|
-
return true;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
function canMoveHorizontally(item, scene) {
|
|
405
|
-
if (scene.getEncodingByItem(item, "x"))
|
|
406
|
-
return false;
|
|
407
|
-
if (item.parent && item.parent.layout) {
|
|
408
|
-
let layout = item.parent.layout;
|
|
409
|
-
if (layout.type == LayoutType.Grid && layout.numCols > 1) {
|
|
410
|
-
return false;
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
if (item.parent && item.parent.type != ItemType.Scene){
|
|
414
|
-
return canMoveHorizontally(item.parent, scene);
|
|
415
|
-
}
|
|
416
|
-
return true;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
function canMoveVertically(item, scene) {
|
|
420
|
-
if (scene.getEncodingByItem(item, "y"))
|
|
421
|
-
return false;
|
|
422
|
-
if (item.parent && item.parent.layout) {
|
|
423
|
-
let layout = item.parent.layout;
|
|
424
|
-
if (layout.type == LayoutType.Grid && layout.numRows > 1) {
|
|
425
|
-
return false;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
if (item.parent && item.parent.type != ItemType.Scene){
|
|
429
|
-
return canMoveVertically(item.parent, scene);
|
|
430
|
-
}
|
|
431
|
-
return true;
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
export function getCommonAncestor(items) {
|
|
435
|
-
let parents = items.map(d => d.parent);
|
|
436
|
-
let uniqueParents = [...new Set(parents)];
|
|
437
|
-
if (uniqueParents.length == 1)
|
|
438
|
-
return uniqueParents[0];
|
|
439
|
-
else
|
|
440
|
-
return getCommonAncestor(parents);
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
export var CanvasProvider = {
|
|
444
|
-
canvas : undefined,
|
|
445
|
-
|
|
446
|
-
getCanvas: function() {
|
|
447
|
-
if (!window)
|
|
448
|
-
return null;
|
|
449
|
-
if (this.canvas === undefined) {
|
|
450
|
-
this.canvas = document.createElement('canvas');
|
|
451
|
-
}
|
|
452
|
-
return this.canvas;
|
|
453
|
-
},
|
|
454
|
-
|
|
455
|
-
getContext: function() {
|
|
456
|
-
var canvas = this.getCanvas();
|
|
457
|
-
return canvas ? canvas.getContext('2d') : null;
|
|
458
|
-
},
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
export var SVGProvider = {
|
|
462
|
-
svg: undefined,
|
|
463
|
-
|
|
464
|
-
getSVG: function() {
|
|
465
|
-
if (!window)
|
|
466
|
-
return null;
|
|
467
|
-
if (this.svg === undefined) {
|
|
468
|
-
this.svg = document.createElement('svg');
|
|
469
|
-
}
|
|
470
|
-
return this.svg;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
// export function getTextWidth(text, font) {
|
|
475
|
-
// let context = CanvasProvider.getContext();
|
|
476
|
-
// context.font = font;
|
|
477
|
-
// let metrics = context.measureText(text);
|
|
478
|
-
// return metrics.width;
|
|
479
|
-
// }
|
|
480
|
-
|
|
481
|
-
export function getTextSize(text, font, fontSize) {
|
|
482
|
-
let context = CanvasProvider.getContext();
|
|
483
|
-
context.font = font;
|
|
484
|
-
let metrics = context.measureText(text);
|
|
485
|
-
if (metrics.fontBoundingBoxAscent)
|
|
486
|
-
return {width: metrics.width, height: metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent};
|
|
487
|
-
else if (metrics.actualBoundingBoxAscent)
|
|
488
|
-
return {width: metrics.width, height: metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent};
|
|
489
|
-
else
|
|
490
|
-
return {width: metrics.width, height: fontSize};
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
export function getAncestorsToAlign (items) {
|
|
494
|
-
let parents = items.map(d => (d.parent && d.parent.type != ItemType.Scene) ? d.parent : d);
|
|
495
|
-
let uniqueParents = [...new Set(parents)];
|
|
496
|
-
if (uniqueParents.length == 1)
|
|
497
|
-
return items;
|
|
498
|
-
else
|
|
499
|
-
return getAncestorsToAlign(parents);
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
export function getTopLevelGroup(item) {
|
|
503
|
-
let parent = item.parent;
|
|
504
|
-
if (parent.type == ItemType.Scene)
|
|
505
|
-
return item;
|
|
506
|
-
else
|
|
507
|
-
return getTopLevelGroup(parent);
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
export function getTopLevelCollection(item) {
|
|
511
|
-
let parent = item.parent;
|
|
512
|
-
if (item.type == ItemType.Collection) {
|
|
513
|
-
if (parent.type == ItemType.Collection) {
|
|
514
|
-
return getTopLevelCollection(parent);
|
|
515
|
-
} else
|
|
516
|
-
return item;
|
|
517
|
-
} else if (parent.type != ItemType.Scene) {
|
|
518
|
-
return getTopLevelCollection(parent);
|
|
519
|
-
} else {
|
|
520
|
-
return undefined;
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
export function polar2Cartesian(cx, cy, r, deg){
|
|
525
|
-
let x = r * Math.cos(degree2radian(deg)),
|
|
526
|
-
y = r * Math.sin(degree2radian(deg));
|
|
527
|
-
return [x + cx, cy - y];
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
export function cartesian2Polar(x, y, cx, cy){
|
|
531
|
-
let d = radian2degree(Math.atan2(cy - y, x - cx));
|
|
532
|
-
d = Math.round( d * 10 + Number.EPSILON ) / 10
|
|
533
|
-
if (d < 0) d += 360;
|
|
534
|
-
let r = Math.sqrt(Math.pow(x-cx, 2) + Math.pow(y-cy, 2));
|
|
535
|
-
r = Math.round( r * 10 + Number.EPSILON ) / 10
|
|
536
|
-
return [d, r];
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
export function degree2radian(d){
|
|
540
|
-
return d * Math.PI/180;
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
export function radian2degree(r){
|
|
544
|
-
return r * 180 / Math.PI;
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
export function CheckAreaOrien(area){
|
|
548
|
-
let VNum = area.vertices.length;
|
|
549
|
-
for (let i = 0; i < area.vertices.length / 2; i++) {
|
|
550
|
-
let Vid1 = i, Vid2 = VNum - i - 1;
|
|
551
|
-
let peer1 = area.vertices[Vid1], peer2 = area.vertices[Vid2]
|
|
552
|
-
if (peer1.x == peer2.x && peer1.y == peer2.y) {
|
|
553
|
-
continue;
|
|
554
|
-
} else {
|
|
555
|
-
if (peer1.x == peer2.x) {
|
|
556
|
-
return "horizontal";
|
|
557
|
-
} else {
|
|
558
|
-
return "vertical";
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
export function getLayout(type, params) {
|
|
565
|
-
let args = params ? params : {};
|
|
566
|
-
switch (type.toLowerCase()) {
|
|
567
|
-
case "grid":
|
|
568
|
-
return new GridLayout(args);
|
|
569
|
-
// case "circular":
|
|
570
|
-
// return new CircularLayout(args);
|
|
571
|
-
case "packing":
|
|
572
|
-
return new PackingLayout(args);
|
|
573
|
-
case "treemap":
|
|
574
|
-
return new TreemapLayout(args);
|
|
575
|
-
case "stack":
|
|
576
|
-
return new StackLayout(args);
|
|
577
|
-
case "tidytree":
|
|
578
|
-
return new TidyTreeLayout(args);
|
|
579
|
-
case "force":
|
|
580
|
-
return new ForceLayout(args);
|
|
581
|
-
case "sugiyama":
|
|
582
|
-
return new SugiyamaLayout(args);
|
|
583
|
-
case "strata":
|
|
584
|
-
return new StrataLayout(args);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// Based on util.Numerical.js, as part of Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
|
|
2
|
-
// http://paperjs.org/
|
|
3
|
-
// Copyright (c) 2011 - 2019, Juerg Lehni & Jonathan Puckey
|
|
4
|
-
// http://scratchdisk.com/ & https://puckey.studio/
|
|
5
|
-
//
|
|
6
|
-
// Distributed under the MIT license. See LICENSE file for detail
|
|
7
|
-
//
|
|
8
|
-
// All rights reserved.
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* A very small absolute value used to check if a value is very close to
|
|
12
|
-
* zero. The value should be large enough to offset any floating point
|
|
13
|
-
* noise, but small enough to be meaningful in computation in a nominal
|
|
14
|
-
* range (see MACHINE_EPSILON).
|
|
15
|
-
*
|
|
16
|
-
* http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
|
|
17
|
-
* http://www.cs.berkeley.edu/~wkahan/Math128/Cubic.pdf
|
|
18
|
-
*/
|
|
19
|
-
export const EPSILON = 1e-12;
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* The epsilon to be used when performing "trigonometric" checks, such
|
|
23
|
-
* as examining cross products to check for collinearity.
|
|
24
|
-
*/
|
|
25
|
-
export const TRIGONOMETRIC_EPSILON = 1e-8;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Checks if the value is 0, within a tolerance defined by
|
|
29
|
-
* Numerical.EPSILON.
|
|
30
|
-
*/
|
|
31
|
-
export function isZero(val) {
|
|
32
|
-
return val >= -EPSILON && val <= EPSILON;
|
|
33
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
<!-- npm install sharp jsdom
|
|
2
|
-
node io.js -->
|
|
3
|
-
<!-- The scripts in this folder serve two purposes: generating and saving of Mascot demo outputs, and performing tests to make sure the demos in the gallery are working. -->
|
|
4
|
-
The scripts in this folder are used to perform tests on the correctness of demos in the gallery. Two kinds of tests are included: pixel-based test (which verifies the demo images) and serialization test (which verify the correctness of the serialization and deserialization code).
|
|
5
|
-
|
|
6
|
-
Note: before performing the pixel-based test, you must generate and save the demo scenes and images by following the steps below:
|
|
7
|
-
|
|
8
|
-
## Generating and Saving Scenes and Images
|
|
9
|
-
To batch generate and save scene graphs, SVG graphics and raster images (PNG format) for the Mascot demos:
|
|
10
|
-
|
|
11
|
-
1. Install dependencies
|
|
12
|
-
puppeteer has been included as a dependency in package.json. Run `npm install` in the Mascot root directory to install the dependcies.
|
|
13
|
-
|
|
14
|
-
2. From the Mascot root directory:
|
|
15
|
-
```bash
|
|
16
|
-
npm run build
|
|
17
|
-
```
|
|
18
|
-
```bash
|
|
19
|
-
npm run start
|
|
20
|
-
```
|
|
21
|
-
If you get (OSError: [Errno 48] Address already in use) error, run `kill -9 $(lsof -t -i:8020)`.
|
|
22
|
-
|
|
23
|
-
3. Switch to the test directory:
|
|
24
|
-
```bash
|
|
25
|
-
cd tests/demo-tests
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
4. Generate and save scenes for the demos using the SVG renderer:
|
|
29
|
-
```bash
|
|
30
|
-
node demos2ScenesSVGs.js
|
|
31
|
-
```
|
|
32
|
-
The scenes will be serialized as .msc files in `io/scene`, and SVGs saved in `io/svg`.
|
|
33
|
-
|
|
34
|
-
5. Convert SVGs to PNG images
|
|
35
|
-
```bash
|
|
36
|
-
node SVG2PNG.js
|
|
37
|
-
```
|
|
38
|
-
The PNG images are saved in the `io/webgl_PNGs` folder.
|
|
39
|
-
|
|
40
|
-
6. (Under development, not working yet) Generate PNG images for the demo using the WebGL renderer:
|
|
41
|
-
```bash
|
|
42
|
-
node demos2CanvasPNGs.js
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## Running Pixel-based Test
|
|
46
|
-
After you have finished generating the scenes and the images, you can perform a pixel-based test which compares the generated image output with the ground truth stored in the `io/demoScreenshots` at the pixel level:
|
|
47
|
-
|
|
48
|
-
1. Dependencies: pngjs and pixelmatch have been included as a dependency in package.json
|
|
49
|
-
|
|
50
|
-
2. Perform pixel-based test on the results of the SVG renderer:
|
|
51
|
-
```bash
|
|
52
|
-
node pixelTest.js svg
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
3. (Not supported yet) Perform pixel-based test on the results of the WebGL renderer:
|
|
56
|
-
```bash
|
|
57
|
-
node pixelTest.js webgl
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Running Serialization Test
|
|
61
|
-
The serialization test converts the scene of each demo to a JSON object, converts the JSON object back to a scene object, and compares the new scene object with the original scene to make sure serialization/deserialization works.
|
|
62
|
-
|
|
63
|
-
1. From the Mascot root directory:
|
|
64
|
-
```bash
|
|
65
|
-
npm run build
|
|
66
|
-
```
|
|
67
|
-
```bash
|
|
68
|
-
npm run start
|
|
69
|
-
```
|
|
70
|
-
If you get (OSError: [Errno 48] Address already in use) error, run `kill -9 $(lsof -t -i:8020)`.
|
|
71
|
-
|
|
72
|
-
2. Switch to the test directory:
|
|
73
|
-
```bash
|
|
74
|
-
cd tests/demo-tests
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
3. Run the test:
|
|
78
|
-
```bash
|
|
79
|
-
node serializationTest.js
|
|
80
|
-
```
|