@yuneta/gobj-ui 7.23.154 → 7.23.156
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/README.md +21 -3
- package/dist/gobj-ui.cjs.js +365 -72
- package/dist/gobj-ui.es.js +366 -73
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +61 -5
- package/src/treedb_elbow.js +113 -0
- package/src/treedb_elbow.test.js +45 -1
- package/src/treedb_layout.js +274 -83
- package/src/treedb_layout.test.js +95 -2
package/dist/gobj-ui.es.js
CHANGED
|
@@ -6,7 +6,7 @@ import { createJSONEditor } from "vanilla-jsoneditor";
|
|
|
6
6
|
import { TabulatorFull } from "tabulator-tables";
|
|
7
7
|
import * as maplibregl from "maplibre-gl";
|
|
8
8
|
import uPlot from "uplot";
|
|
9
|
-
import { BaseLayout, BrushSelect, CanvasEvent, Circle, CommonEvent, DragCanvas, EdgeEvent, ExtensionCategory, Graph, HTML, HistoryEvent, NodeEvent, Polyline, Toolbar, ZoomCanvas, register } from "@antv/g6";
|
|
9
|
+
import { BaseLayout, BrushSelect, CanvasEvent, Circle, CommonEvent, Cubic, CubicHorizontal, DragCanvas, EdgeEvent, ExtensionCategory, Graph, HTML, HistoryEvent, NodeEvent, Polyline, Toolbar, ZoomCanvas, register } from "@antv/g6";
|
|
10
10
|
//#region \0rolldown/runtime.js
|
|
11
11
|
var __create = Object.create;
|
|
12
12
|
var __defProp = Object.defineProperty;
|
|
@@ -29418,6 +29418,56 @@ function stack_trunk_width(k) {
|
|
|
29418
29418
|
let lanes = Math.max(0, k - 2);
|
|
29419
29419
|
return Math.max(36, 20 + Math.max(0, lanes - 1) * 6);
|
|
29420
29420
|
}
|
|
29421
|
+
/************************************************************
|
|
29422
|
+
* The children of every node, with each run of STACK_MIN_RUN or
|
|
29423
|
+
* more consecutive LEAF children replaced by one STACK. Runs, not
|
|
29424
|
+
* all the leaves of a parent: the children keep their order. A
|
|
29425
|
+
* stack's key is an OBJECT, so it can never be taken for a node id,
|
|
29426
|
+
* which is a string. Shared by the compact tree and the radial.
|
|
29427
|
+
*
|
|
29428
|
+
* Returns {kids_of: Map<id, [id | stack]>, stacks: Map<stack, {ids, depth}>}
|
|
29429
|
+
************************************************************/
|
|
29430
|
+
function leaf_runs(t) {
|
|
29431
|
+
let kids_of = /* @__PURE__ */ new Map();
|
|
29432
|
+
let stacks = /* @__PURE__ */ new Map();
|
|
29433
|
+
for (let [id, kids] of t.children) {
|
|
29434
|
+
let out = [];
|
|
29435
|
+
let run = [];
|
|
29436
|
+
let flush = () => {
|
|
29437
|
+
if (run.length >= 3) {
|
|
29438
|
+
let key = { stack: stacks.size };
|
|
29439
|
+
stacks.set(key, {
|
|
29440
|
+
ids: run,
|
|
29441
|
+
depth: t.depth.get(run[0])
|
|
29442
|
+
});
|
|
29443
|
+
out.push(key);
|
|
29444
|
+
} else out.push(...run);
|
|
29445
|
+
run = [];
|
|
29446
|
+
};
|
|
29447
|
+
for (let kid of kids) if ((t.children.get(kid) || []).length === 0) run.push(kid);
|
|
29448
|
+
else {
|
|
29449
|
+
flush();
|
|
29450
|
+
out.push(kid);
|
|
29451
|
+
}
|
|
29452
|
+
flush();
|
|
29453
|
+
kids_of.set(id, out);
|
|
29454
|
+
}
|
|
29455
|
+
return {
|
|
29456
|
+
kids_of,
|
|
29457
|
+
stacks
|
|
29458
|
+
};
|
|
29459
|
+
}
|
|
29460
|
+
function stacked_order(t, kids_of) {
|
|
29461
|
+
let order = [];
|
|
29462
|
+
let todo = t.roots.slice().reverse();
|
|
29463
|
+
while (todo.length) {
|
|
29464
|
+
let id = todo.pop();
|
|
29465
|
+
order.push(id);
|
|
29466
|
+
let kids = kids_of.get(id) || [];
|
|
29467
|
+
for (let i = kids.length - 1; i >= 0; i--) todo.push(kids[i]);
|
|
29468
|
+
}
|
|
29469
|
+
return order;
|
|
29470
|
+
}
|
|
29421
29471
|
function stack_geometry(t, st, col_x, col_w) {
|
|
29422
29472
|
let d = st.depth;
|
|
29423
29473
|
let k = st.ids.length;
|
|
@@ -29457,38 +29507,8 @@ function place_stack(t, st, g, top, pos) {
|
|
|
29457
29507
|
function compact_tree_lr(nodes, edges, o) {
|
|
29458
29508
|
let t = spanning_tree(nodes, edges);
|
|
29459
29509
|
let pos = /* @__PURE__ */ new Map();
|
|
29460
|
-
let kids_of
|
|
29461
|
-
let
|
|
29462
|
-
for (let [id, kids] of t.children) {
|
|
29463
|
-
let out = [];
|
|
29464
|
-
let run = [];
|
|
29465
|
-
let flush = () => {
|
|
29466
|
-
if (run.length >= 3) {
|
|
29467
|
-
let key = { stack: stacks.size };
|
|
29468
|
-
stacks.set(key, {
|
|
29469
|
-
ids: run,
|
|
29470
|
-
depth: t.depth.get(run[0])
|
|
29471
|
-
});
|
|
29472
|
-
out.push(key);
|
|
29473
|
-
} else out.push(...run);
|
|
29474
|
-
run = [];
|
|
29475
|
-
};
|
|
29476
|
-
for (let kid of kids) if ((t.children.get(kid) || []).length === 0) run.push(kid);
|
|
29477
|
-
else {
|
|
29478
|
-
flush();
|
|
29479
|
-
out.push(kid);
|
|
29480
|
-
}
|
|
29481
|
-
flush();
|
|
29482
|
-
kids_of.set(id, out);
|
|
29483
|
-
}
|
|
29484
|
-
let order = [];
|
|
29485
|
-
let todo = t.roots.slice().reverse();
|
|
29486
|
-
while (todo.length) {
|
|
29487
|
-
let id = todo.pop();
|
|
29488
|
-
order.push(id);
|
|
29489
|
-
let kids = kids_of.get(id) || [];
|
|
29490
|
-
for (let i = kids.length - 1; i >= 0; i--) todo.push(kids[i]);
|
|
29491
|
-
}
|
|
29510
|
+
let { kids_of, stacks } = leaf_runs(t);
|
|
29511
|
+
let order = stacked_order(t, kids_of);
|
|
29492
29512
|
let col_w = [];
|
|
29493
29513
|
for (let [id, d] of t.depth) col_w[d] = Math.max(col_w[d] || 0, t.by_id.get(id).w);
|
|
29494
29514
|
let col_x = [];
|
|
@@ -29625,56 +29645,103 @@ function extent_at(n, a) {
|
|
|
29625
29645
|
*
|
|
29626
29646
|
* ranksep the step between rings
|
|
29627
29647
|
* nodesep the gap between neighbours on a ring
|
|
29648
|
+
* stack (default true) a run of three or more LEAF children
|
|
29649
|
+
* is a STACK, as in the compact tree: it asks its
|
|
29650
|
+
* ring for one row of about the square root of its
|
|
29651
|
+
* cards, not for every leaf -- a hall with a hundred
|
|
29652
|
+
* devices no longer blows the ring up -- and lays
|
|
29653
|
+
* them in rows going OUTWARD, each row as full as
|
|
29654
|
+
* the room it has: rings round the parent when it is
|
|
29655
|
+
* alone, a fan inside its sector when it is not.
|
|
29656
|
+
* false keeps every leaf on the ring.
|
|
29628
29657
|
************************************************************/
|
|
29629
29658
|
function layout_radial(nodes, edges, opts) {
|
|
29630
|
-
let o = Object.assign({}, DEFAULTS, opts || {});
|
|
29659
|
+
let o = Object.assign({}, DEFAULTS, { stack: true }, opts || {});
|
|
29631
29660
|
let t = spanning_tree(nodes, edges);
|
|
29632
29661
|
let pos = /* @__PURE__ */ new Map();
|
|
29633
29662
|
if (!t.roots.length) return pos;
|
|
29634
|
-
let
|
|
29635
|
-
|
|
29663
|
+
let runs = o.stack ? leaf_runs(t) : {
|
|
29664
|
+
kids_of: t.children,
|
|
29665
|
+
stacks: /* @__PURE__ */ new Map()
|
|
29666
|
+
};
|
|
29667
|
+
let kids_of = runs.kids_of;
|
|
29668
|
+
let stacks = runs.stacks;
|
|
29669
|
+
let order = stacked_order(t, kids_of);
|
|
29670
|
+
for (let st of stacks.values()) {
|
|
29671
|
+
st.per_row = Math.ceil(Math.sqrt(st.ids.length));
|
|
29672
|
+
st.cards = st.ids.map((id) => t.by_id.get(id));
|
|
29673
|
+
}
|
|
29674
|
+
let stack_across = (st, a) => {
|
|
29675
|
+
let w = 0;
|
|
29676
|
+
for (let c of st.cards) w = Math.max(w, extent_at(c, a + Math.PI / 2));
|
|
29677
|
+
return {
|
|
29678
|
+
card: w,
|
|
29679
|
+
row: st.per_row * w + (st.per_row - 1) * o.nodesep
|
|
29680
|
+
};
|
|
29681
|
+
};
|
|
29682
|
+
let widest_along = (cards, a, half) => {
|
|
29683
|
+
let e = 0;
|
|
29684
|
+
for (let k = 0; k <= 16; k++) {
|
|
29685
|
+
let th = a - half + 2 * half * k / 16;
|
|
29686
|
+
for (let c of cards) e = Math.max(e, extent_at(c, th));
|
|
29687
|
+
}
|
|
29688
|
+
return e;
|
|
29689
|
+
};
|
|
29690
|
+
let depth_of = (id) => stacks.has(id) ? stacks.get(id).depth : t.depth.get(id);
|
|
29691
|
+
let circ = (a, b) => {
|
|
29692
|
+
let d = Math.abs(a - b) % (2 * Math.PI);
|
|
29693
|
+
return d > Math.PI ? 2 * Math.PI - d : d;
|
|
29694
|
+
};
|
|
29695
|
+
let weight = /* @__PURE__ */ new Map();
|
|
29636
29696
|
for (let i = order.length - 1; i >= 0; i--) {
|
|
29637
29697
|
let id = order[i];
|
|
29638
|
-
let
|
|
29698
|
+
let st = stacks.get(id);
|
|
29699
|
+
if (st) {
|
|
29700
|
+
weight.set(id, st.per_row);
|
|
29701
|
+
continue;
|
|
29702
|
+
}
|
|
29703
|
+
let kids = kids_of.get(id) || [];
|
|
29639
29704
|
if (!kids.length) {
|
|
29640
|
-
|
|
29705
|
+
weight.set(id, 1);
|
|
29641
29706
|
continue;
|
|
29642
29707
|
}
|
|
29643
29708
|
let n = 0;
|
|
29644
|
-
for (let kid of kids) n +=
|
|
29645
|
-
|
|
29709
|
+
for (let kid of kids) n += weight.get(kid);
|
|
29710
|
+
weight.set(id, n);
|
|
29646
29711
|
}
|
|
29647
29712
|
let total = 0;
|
|
29648
|
-
for (let root of t.roots) total +=
|
|
29713
|
+
for (let root of t.roots) total += weight.get(root);
|
|
29649
29714
|
let single = t.roots.length === 1;
|
|
29650
|
-
let ring_of = (id) =>
|
|
29715
|
+
let ring_of = (id) => depth_of(id) + (single ? 0 : 1);
|
|
29651
29716
|
let angle = /* @__PURE__ */ new Map();
|
|
29652
29717
|
let rings = [];
|
|
29653
29718
|
let sector = (root_id, root_from, root_span, root_parent) => {
|
|
29654
|
-
let
|
|
29719
|
+
let todo = [{
|
|
29655
29720
|
id: root_id,
|
|
29656
29721
|
from: root_from,
|
|
29657
29722
|
span: root_span,
|
|
29658
29723
|
parent: root_parent
|
|
29659
29724
|
}];
|
|
29660
|
-
while (
|
|
29661
|
-
let { id, from, span, parent } =
|
|
29725
|
+
while (todo.length) {
|
|
29726
|
+
let { id, from, span, parent } = todo.pop();
|
|
29662
29727
|
let a = from + span / 2;
|
|
29663
29728
|
angle.set(id, a);
|
|
29664
29729
|
let ring = ring_of(id);
|
|
29665
29730
|
if (!rings[ring]) rings[ring] = [];
|
|
29666
|
-
let
|
|
29731
|
+
let st = stacks.get(id);
|
|
29732
|
+
let n = st ? null : t.by_id.get(id);
|
|
29667
29733
|
rings[ring].push({
|
|
29668
29734
|
id,
|
|
29669
29735
|
angle: a,
|
|
29670
|
-
|
|
29671
|
-
|
|
29672
|
-
|
|
29736
|
+
span,
|
|
29737
|
+
diag: st ? stack_across(st, a).row : Math.hypot(n.w, n.h),
|
|
29738
|
+
ext: st ? widest_along(st.cards, a, Math.min(span / 2, Math.PI)) : extent_at(n, a),
|
|
29739
|
+
parent_ext: !parent ? 0 : st ? widest_along([t.by_id.get(parent)], a, Math.min(span / 2, Math.PI)) : extent_at(t.by_id.get(parent), a)
|
|
29673
29740
|
});
|
|
29674
29741
|
let cursor = from;
|
|
29675
|
-
for (let kid of
|
|
29676
|
-
let part = span *
|
|
29677
|
-
|
|
29742
|
+
for (let kid of kids_of.get(id) || []) {
|
|
29743
|
+
let part = span * weight.get(kid) / weight.get(id);
|
|
29744
|
+
todo.push({
|
|
29678
29745
|
id: kid,
|
|
29679
29746
|
from: cursor,
|
|
29680
29747
|
span: part,
|
|
@@ -29688,38 +29755,120 @@ function layout_radial(nodes, edges, opts) {
|
|
|
29688
29755
|
let root = t.roots[0];
|
|
29689
29756
|
angle.set(root, 0);
|
|
29690
29757
|
let cursor = -Math.PI / 2;
|
|
29691
|
-
for (let kid of
|
|
29692
|
-
let part = 2 * Math.PI *
|
|
29758
|
+
for (let kid of kids_of.get(root) || []) {
|
|
29759
|
+
let part = 2 * Math.PI * weight.get(kid) / weight.get(root);
|
|
29693
29760
|
sector(kid, cursor, part, root);
|
|
29694
29761
|
cursor += part;
|
|
29695
29762
|
}
|
|
29696
29763
|
} else {
|
|
29697
29764
|
let cursor = -Math.PI / 2;
|
|
29698
29765
|
for (let root of t.roots) {
|
|
29699
|
-
let part = 2 * Math.PI *
|
|
29766
|
+
let part = 2 * Math.PI * weight.get(root) / total;
|
|
29700
29767
|
sector(root, cursor, part, null);
|
|
29701
29768
|
cursor += part;
|
|
29702
29769
|
}
|
|
29703
29770
|
}
|
|
29771
|
+
let fit = (list, r0) => {
|
|
29772
|
+
let r = r0;
|
|
29773
|
+
let sorted = list.slice().sort((a, b) => a.angle - b.angle);
|
|
29774
|
+
for (let i = 0; i < sorted.length && sorted.length > 1; i++) {
|
|
29775
|
+
let a = sorted[i];
|
|
29776
|
+
let b = sorted[(i + 1) % sorted.length];
|
|
29777
|
+
let gap = i + 1 < sorted.length ? b.angle - a.angle : b.angle + 2 * Math.PI - a.angle;
|
|
29778
|
+
if (gap > 1e-9) r = Math.max(r, (a.diag / 2 + b.diag / 2 + o.nodesep) / gap);
|
|
29779
|
+
}
|
|
29780
|
+
return r;
|
|
29781
|
+
};
|
|
29704
29782
|
let radius = [0];
|
|
29783
|
+
let reaching = [];
|
|
29705
29784
|
for (let ring = 1; ring < rings.length; ring++) {
|
|
29785
|
+
let members = rings[ring] || [];
|
|
29706
29786
|
let r = radius[ring - 1] + o.ranksep;
|
|
29707
|
-
|
|
29708
|
-
|
|
29709
|
-
|
|
29710
|
-
|
|
29711
|
-
|
|
29712
|
-
|
|
29713
|
-
|
|
29787
|
+
let band = 0;
|
|
29788
|
+
for (let n of members) {
|
|
29789
|
+
r = Math.max(r, radius[ring - 1] + (n.parent_ext + n.ext) / 2 + o.nodesep);
|
|
29790
|
+
band = Math.max(band, n.ext);
|
|
29791
|
+
}
|
|
29792
|
+
r = fit(members, r);
|
|
29793
|
+
for (let pass = 0; pass < 2; pass++) for (let g of reaching) {
|
|
29794
|
+
if (g.reach < r - band / 2 - o.nodesep) continue;
|
|
29795
|
+
for (let m of members) {
|
|
29796
|
+
let d = circ(g.angle, m.angle);
|
|
29797
|
+
if (d > g.half + 1e-9) r = Math.max(r, (m.diag / 2 + o.nodesep) / (d - g.half));
|
|
29798
|
+
else r = Math.max(r, g.reach + m.ext / 2 + o.nodesep);
|
|
29799
|
+
}
|
|
29714
29800
|
}
|
|
29715
29801
|
radius[ring] = r;
|
|
29802
|
+
let sorted = members.slice().sort((a, b) => a.angle - b.angle);
|
|
29803
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
29804
|
+
let m = sorted[i];
|
|
29805
|
+
let st = stacks.get(m.id);
|
|
29806
|
+
if (!st) continue;
|
|
29807
|
+
let room = m.span / 2;
|
|
29808
|
+
if (sorted.length > 1) {
|
|
29809
|
+
let left = sorted[(i - 1 + sorted.length) % sorted.length];
|
|
29810
|
+
let right = sorted[(i + 1) % sorted.length];
|
|
29811
|
+
room = Math.min(room, circ(m.angle, left.angle) - (left.diag / 2 + o.nodesep) / r, circ(m.angle, right.angle) - (right.diag / 2 + o.nodesep) / r);
|
|
29812
|
+
}
|
|
29813
|
+
room = Math.min(room, Math.PI);
|
|
29814
|
+
let across = 0;
|
|
29815
|
+
let along = 0;
|
|
29816
|
+
for (let k = 0; k <= 16; k++) {
|
|
29817
|
+
let th = m.angle - room + 2 * room * k / 16;
|
|
29818
|
+
for (let c of st.cards) {
|
|
29819
|
+
across = Math.max(across, extent_at(c, th + Math.PI / 2));
|
|
29820
|
+
along = Math.max(along, extent_at(c, th));
|
|
29821
|
+
}
|
|
29822
|
+
}
|
|
29823
|
+
let rows = [];
|
|
29824
|
+
let left_to_place = st.ids.length;
|
|
29825
|
+
let rr = r;
|
|
29826
|
+
let half = 0;
|
|
29827
|
+
while (left_to_place > 0) {
|
|
29828
|
+
let fits = Math.floor(2 * room * rr / (across + o.nodesep));
|
|
29829
|
+
let cnt = Math.max(1, Math.min(left_to_place, fits));
|
|
29830
|
+
rows.push({
|
|
29831
|
+
rr,
|
|
29832
|
+
cnt
|
|
29833
|
+
});
|
|
29834
|
+
half = Math.max(half, (cnt * (across + o.nodesep) - o.nodesep) / 2 / rr);
|
|
29835
|
+
left_to_place -= cnt;
|
|
29836
|
+
rr += along + 40;
|
|
29837
|
+
}
|
|
29838
|
+
st.plan = {
|
|
29839
|
+
angle: m.angle,
|
|
29840
|
+
across,
|
|
29841
|
+
rows
|
|
29842
|
+
};
|
|
29843
|
+
reaching.push({
|
|
29844
|
+
angle: m.angle,
|
|
29845
|
+
half,
|
|
29846
|
+
reach: rows[rows.length - 1].rr + along / 2
|
|
29847
|
+
});
|
|
29848
|
+
}
|
|
29716
29849
|
}
|
|
29717
29850
|
for (let [id, a] of angle) {
|
|
29718
|
-
let
|
|
29719
|
-
|
|
29720
|
-
|
|
29721
|
-
|
|
29722
|
-
|
|
29851
|
+
let st = stacks.get(id);
|
|
29852
|
+
if (!st) {
|
|
29853
|
+
let r0 = radius[ring_of(id)] || 0;
|
|
29854
|
+
pos.set(id, {
|
|
29855
|
+
x: r0 * Math.cos(a),
|
|
29856
|
+
y: r0 * Math.sin(a)
|
|
29857
|
+
});
|
|
29858
|
+
continue;
|
|
29859
|
+
}
|
|
29860
|
+
let i = 0;
|
|
29861
|
+
for (let row of st.plan.rows) {
|
|
29862
|
+
let step = (st.plan.across + o.nodesep) / row.rr;
|
|
29863
|
+
for (let j = 0; j < row.cnt; j++) {
|
|
29864
|
+
let th = a + (j - (row.cnt - 1) / 2) * step;
|
|
29865
|
+
pos.set(st.ids[i], {
|
|
29866
|
+
x: row.rr * Math.cos(th),
|
|
29867
|
+
y: row.rr * Math.sin(th)
|
|
29868
|
+
});
|
|
29869
|
+
i++;
|
|
29870
|
+
}
|
|
29871
|
+
}
|
|
29723
29872
|
}
|
|
29724
29873
|
return pos;
|
|
29725
29874
|
}
|
|
@@ -30163,6 +30312,112 @@ function elbow_route(s, t, box_s, box_t, lane, vertical, boxes, stagger) {
|
|
|
30163
30312
|
if (!route && near.length < others.length) route = orth_search(a, z, others.map((b) => box_expand(b, m)));
|
|
30164
30313
|
return route || simple;
|
|
30165
30314
|
}
|
|
30315
|
+
function path_points(path) {
|
|
30316
|
+
let pts = [];
|
|
30317
|
+
let cur = null;
|
|
30318
|
+
for (let c of path) if (c[0] === "M" || c[0] === "L") {
|
|
30319
|
+
cur = [c[1], c[2]];
|
|
30320
|
+
pts.push(cur);
|
|
30321
|
+
} else if (c[0] === "C" && cur) {
|
|
30322
|
+
let [x0, y0] = cur;
|
|
30323
|
+
for (let k = 1; k <= 16; k++) {
|
|
30324
|
+
let u = k / 16;
|
|
30325
|
+
let v = 1 - u;
|
|
30326
|
+
pts.push([v * v * v * x0 + 3 * v * v * u * c[1] + 3 * v * u * u * c[3] + u * u * u * c[5], v * v * v * y0 + 3 * v * v * u * c[2] + 3 * v * u * u * c[4] + u * u * u * c[6]]);
|
|
30327
|
+
}
|
|
30328
|
+
cur = [c[5], c[6]];
|
|
30329
|
+
} else if (c[0] === "Q" && cur) {
|
|
30330
|
+
let [x0, y0] = cur;
|
|
30331
|
+
for (let k = 1; k <= 16; k++) {
|
|
30332
|
+
let u = k / 16;
|
|
30333
|
+
let v = 1 - u;
|
|
30334
|
+
pts.push([v * v * x0 + 2 * v * u * c[1] + u * u * c[3], v * v * y0 + 2 * v * u * c[2] + u * u * c[4]]);
|
|
30335
|
+
}
|
|
30336
|
+
cur = [c[3], c[4]];
|
|
30337
|
+
}
|
|
30338
|
+
return pts;
|
|
30339
|
+
}
|
|
30340
|
+
/************************************************************
|
|
30341
|
+
* Does the G6 path `path` of a curved edge cross a card other than
|
|
30342
|
+
* its own two? Measured on the curve itself -- the path G6 would
|
|
30343
|
+
* draw, sampled -- and not on the rectangle round it, which took
|
|
30344
|
+
* every card the curve merely passed near: the ports of a row
|
|
30345
|
+
* stick well into the space above it. Its own two cards are left
|
|
30346
|
+
* out: the curve starts and ends on their ports.
|
|
30347
|
+
************************************************************/
|
|
30348
|
+
function curve_hits(path, boxes, box_s, box_t) {
|
|
30349
|
+
let pts = path_points(path);
|
|
30350
|
+
if (pts.length < 2) return false;
|
|
30351
|
+
let bb = {
|
|
30352
|
+
x1: Infinity,
|
|
30353
|
+
y1: Infinity,
|
|
30354
|
+
x2: -Infinity,
|
|
30355
|
+
y2: -Infinity
|
|
30356
|
+
};
|
|
30357
|
+
for (let p of pts) {
|
|
30358
|
+
bb.x1 = Math.min(bb.x1, p[0]);
|
|
30359
|
+
bb.y1 = Math.min(bb.y1, p[1]);
|
|
30360
|
+
bb.x2 = Math.max(bb.x2, p[0]);
|
|
30361
|
+
bb.y2 = Math.max(bb.y2, p[1]);
|
|
30362
|
+
}
|
|
30363
|
+
for (let b of boxes || []) {
|
|
30364
|
+
if (same_box(b, box_s) || same_box(b, box_t) || !box_overlaps(b, box_expand(bb, 1))) continue;
|
|
30365
|
+
let inner = box_expand(b, -1);
|
|
30366
|
+
for (let k = 0; k + 1 < pts.length; k++) if (segment_hits(pts[k], pts[k + 1], inner)) return true;
|
|
30367
|
+
}
|
|
30368
|
+
return false;
|
|
30369
|
+
}
|
|
30370
|
+
/************************************************************
|
|
30371
|
+
* A G6 path (['M'|'L'|'Q', ...]) along `points` with every corner
|
|
30372
|
+
* rounded -- by `radius`, or by half the shorter of its two
|
|
30373
|
+
* segments, so a short run is never overshot. The rounding is the
|
|
30374
|
+
* quadratic G6's own polyline uses.
|
|
30375
|
+
************************************************************/
|
|
30376
|
+
function rounded_path(points, radius) {
|
|
30377
|
+
let path = [[
|
|
30378
|
+
"M",
|
|
30379
|
+
points[0][0],
|
|
30380
|
+
points[0][1]
|
|
30381
|
+
]];
|
|
30382
|
+
for (let i = 1; i + 1 < points.length; i++) {
|
|
30383
|
+
let a = points[i - 1];
|
|
30384
|
+
let m = points[i];
|
|
30385
|
+
let b = points[i + 1];
|
|
30386
|
+
let len_in = Math.hypot(m[0] - a[0], m[1] - a[1]);
|
|
30387
|
+
let len_out = Math.hypot(b[0] - m[0], b[1] - m[1]);
|
|
30388
|
+
let r = Math.min(radius, len_in / 2, len_out / 2);
|
|
30389
|
+
let collinear = Math.abs((m[0] - a[0]) * (b[1] - m[1]) - (m[1] - a[1]) * (b[0] - m[0])) < 1e-9;
|
|
30390
|
+
if (r <= 0 || collinear) {
|
|
30391
|
+
path.push([
|
|
30392
|
+
"L",
|
|
30393
|
+
m[0],
|
|
30394
|
+
m[1]
|
|
30395
|
+
]);
|
|
30396
|
+
continue;
|
|
30397
|
+
}
|
|
30398
|
+
let p1 = [m[0] - (m[0] - a[0]) / len_in * r, m[1] - (m[1] - a[1]) / len_in * r];
|
|
30399
|
+
let p2 = [m[0] + (b[0] - m[0]) / len_out * r, m[1] + (b[1] - m[1]) / len_out * r];
|
|
30400
|
+
path.push([
|
|
30401
|
+
"L",
|
|
30402
|
+
p1[0],
|
|
30403
|
+
p1[1]
|
|
30404
|
+
]);
|
|
30405
|
+
path.push([
|
|
30406
|
+
"Q",
|
|
30407
|
+
m[0],
|
|
30408
|
+
m[1],
|
|
30409
|
+
p2[0],
|
|
30410
|
+
p2[1]
|
|
30411
|
+
]);
|
|
30412
|
+
}
|
|
30413
|
+
let last = points[points.length - 1];
|
|
30414
|
+
path.push([
|
|
30415
|
+
"L",
|
|
30416
|
+
last[0],
|
|
30417
|
+
last[1]
|
|
30418
|
+
]);
|
|
30419
|
+
return path;
|
|
30420
|
+
}
|
|
30166
30421
|
//#endregion
|
|
30167
30422
|
//#region node_modules/@babel/runtime/helpers/esm/typeof.js
|
|
30168
30423
|
function _typeof(o) {
|
|
@@ -55050,7 +55305,7 @@ Easing Functions from anime.js, they are tried and true, so, its better to use t
|
|
|
55050
55305
|
var Quad = function Quad(t) {
|
|
55051
55306
|
return Math.pow(t, 2);
|
|
55052
55307
|
};
|
|
55053
|
-
var Cubic = function Cubic(t) {
|
|
55308
|
+
var Cubic$1 = function Cubic(t) {
|
|
55054
55309
|
return Math.pow(t, 3);
|
|
55055
55310
|
};
|
|
55056
55311
|
var Quart = function Quart(t) {
|
|
@@ -55187,10 +55442,10 @@ var EasingFunctions = {
|
|
|
55187
55442
|
"out-quad": EaseOut(Quad),
|
|
55188
55443
|
"in-out-quad": EaseInOut(Quad),
|
|
55189
55444
|
"out-in-quad": EaseOutIn(Quad),
|
|
55190
|
-
"in-cubic": Cubic,
|
|
55191
|
-
"out-cubic": EaseOut(Cubic),
|
|
55192
|
-
"in-out-cubic": EaseInOut(Cubic),
|
|
55193
|
-
"out-in-cubic": EaseOutIn(Cubic),
|
|
55445
|
+
"in-cubic": Cubic$1,
|
|
55446
|
+
"out-cubic": EaseOut(Cubic$1),
|
|
55447
|
+
"in-out-cubic": EaseInOut(Cubic$1),
|
|
55448
|
+
"out-in-cubic": EaseOutIn(Cubic$1),
|
|
55194
55449
|
"in-quart": Quart,
|
|
55195
55450
|
"out-quart": EaseOut(Quart),
|
|
55196
55451
|
"in-out-quart": EaseInOut(Quart),
|
|
@@ -57363,6 +57618,8 @@ function register_layouts(gobj) {
|
|
|
57363
57618
|
register(ExtensionCategory.LAYOUT, "treedb-compact", TreedbCompactLayout);
|
|
57364
57619
|
register(ExtensionCategory.EDGE, "treedb-elbow-v", TreedbElbowV);
|
|
57365
57620
|
register(ExtensionCategory.EDGE, "treedb-elbow-h", TreedbElbowH);
|
|
57621
|
+
register(ExtensionCategory.EDGE, "treedb-curve-v", TreedbCurveV);
|
|
57622
|
+
register(ExtensionCategory.EDGE, "treedb-curve-h", TreedbCurveH);
|
|
57366
57623
|
register(ExtensionCategory.LAYOUT, "treedb-radial", TreedbRadialLayout);
|
|
57367
57624
|
register(ExtensionCategory.NODE, "light", LightNode);
|
|
57368
57625
|
register(ExtensionCategory.NODE, "treedb-card", TreedbCard);
|
|
@@ -58057,7 +58314,9 @@ function layout_direction(gobj) {
|
|
|
58057
58314
|
function edge_type_for(gobj) {
|
|
58058
58315
|
let lr = layout_direction(gobj) === "LR";
|
|
58059
58316
|
let rowless = gobj_read_attr(gobj, "rowless_layouts") || [];
|
|
58060
|
-
|
|
58317
|
+
let rows = !str_in_list(rowless, gobj.priv.layout);
|
|
58318
|
+
if (rows && gobj_read_str_attr(gobj, "edge_shape") === "elbow") return lr ? "treedb-elbow-h" : "treedb-elbow-v";
|
|
58319
|
+
if (rows) return lr ? "treedb-curve-h" : "treedb-curve-v";
|
|
58061
58320
|
return lr ? "cubic-horizontal" : "cubic";
|
|
58062
58321
|
}
|
|
58063
58322
|
/************************************************************
|
|
@@ -59661,6 +59920,40 @@ var TreedbElbowH = class extends Polyline {
|
|
|
59661
59920
|
return super.getKeyPath(Object.assign({}, attributes, { radius: attributes.radius || ELBOW_RADIUS }));
|
|
59662
59921
|
}
|
|
59663
59922
|
};
|
|
59923
|
+
/************************************************************
|
|
59924
|
+
* A CURVED edge that keeps off the cards. G6's cubic, as before,
|
|
59925
|
+
* unless that very curve -- sampled, not guessed from the
|
|
59926
|
+
* rectangle round it -- would cross a card other than its own two,
|
|
59927
|
+
* or when it does not run forward and so would cross its own:
|
|
59928
|
+
* the card above a lower row of a stack, a row between a parent
|
|
59929
|
+
* and a far child. Then it goes the way an elbow would (the comb,
|
|
59930
|
+
* the detour, the route: the same lanes and staggered turns) with
|
|
59931
|
+
* round corners, so it still reads as a curve. `-v` for rows
|
|
59932
|
+
* stacked top to bottom, `-h` for columns.
|
|
59933
|
+
************************************************************/
|
|
59934
|
+
function curve_key_path(edge, attributes, vertical, plain) {
|
|
59935
|
+
let [s, t] = edge.getEndpoints(attributes, false);
|
|
59936
|
+
let along = vertical ? 1 : 0;
|
|
59937
|
+
let box_s = elbow_box(edge.sourceNode);
|
|
59938
|
+
let box_t = elbow_box(edge.targetNode);
|
|
59939
|
+
let boxes = elbow_obstacles(edge);
|
|
59940
|
+
if (t[along] - s[along] > 20 && !curve_hits(plain, boxes, box_s, box_t)) return plain;
|
|
59941
|
+
return rounded_path([
|
|
59942
|
+
s,
|
|
59943
|
+
...elbow_route(s, t, box_s, box_t, elbow_lane_of(edge), vertical, boxes, elbow_stagger_of(edge, vertical)),
|
|
59944
|
+
t
|
|
59945
|
+
], 24);
|
|
59946
|
+
}
|
|
59947
|
+
var TreedbCurveV = class extends Cubic {
|
|
59948
|
+
getKeyPath(attributes) {
|
|
59949
|
+
return curve_key_path(this, attributes, true, super.getKeyPath(attributes));
|
|
59950
|
+
}
|
|
59951
|
+
};
|
|
59952
|
+
var TreedbCurveH = class extends CubicHorizontal {
|
|
59953
|
+
getKeyPath(attributes) {
|
|
59954
|
+
return curve_key_path(this, attributes, false, super.getKeyPath(attributes));
|
|
59955
|
+
}
|
|
59956
|
+
};
|
|
59664
59957
|
var TreedbCompactLayout = class extends BaseLayout {
|
|
59665
59958
|
async execute(data, options) {
|
|
59666
59959
|
let input = treedb_layout_input(data);
|
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -133,7 +133,10 @@ import {
|
|
|
133
133
|
fold_root_group_key,
|
|
134
134
|
} from "./treedb_fold_model.js";
|
|
135
135
|
import {layout_tree, layout_radial, layout_compact} from "./treedb_layout.js";
|
|
136
|
-
import {
|
|
136
|
+
import {
|
|
137
|
+
elbow_lane, elbow_rank, elbow_route, elbow_combs, curve_hits, rounded_path, CURVE_RADIUS,
|
|
138
|
+
ELBOW_STEP,
|
|
139
|
+
} from "./treedb_elbow.js";
|
|
137
140
|
|
|
138
141
|
import {
|
|
139
142
|
BaseLayout,
|
|
@@ -148,6 +151,8 @@ import {
|
|
|
148
151
|
Toolbar,
|
|
149
152
|
register,
|
|
150
153
|
Polyline,
|
|
154
|
+
Cubic,
|
|
155
|
+
CubicHorizontal,
|
|
151
156
|
} from '@antv/g6';
|
|
152
157
|
|
|
153
158
|
import {Circle as CircleGeometry, Rect as RectGeometry} from '@antv/g';
|
|
@@ -942,6 +947,8 @@ function register_layouts(gobj)
|
|
|
942
947
|
register(ExtensionCategory.LAYOUT, 'treedb-compact', TreedbCompactLayout);
|
|
943
948
|
register(ExtensionCategory.EDGE, 'treedb-elbow-v', TreedbElbowV);
|
|
944
949
|
register(ExtensionCategory.EDGE, 'treedb-elbow-h', TreedbElbowH);
|
|
950
|
+
register(ExtensionCategory.EDGE, 'treedb-curve-v', TreedbCurveV);
|
|
951
|
+
register(ExtensionCategory.EDGE, 'treedb-curve-h', TreedbCurveH);
|
|
945
952
|
register(ExtensionCategory.LAYOUT, 'treedb-radial', TreedbRadialLayout);
|
|
946
953
|
register(ExtensionCategory.NODE, 'light', LightNode);
|
|
947
954
|
register(ExtensionCategory.NODE, 'treedb-card', TreedbCard);
|
|
@@ -2042,16 +2049,20 @@ function layout_direction(gobj)
|
|
|
2042
2049
|
return str_in_list(LR_LAYOUTS, gobj.priv.layout)? "LR" : "TB";
|
|
2043
2050
|
}
|
|
2044
2051
|
|
|
2045
|
-
/*
|
|
2046
|
-
* has rows
|
|
2052
|
+
/* An elbow when the reader asked for one, a curve otherwise -- ours
|
|
2053
|
+
* where the layout has rows, which keeps off the cards; G6's plain
|
|
2054
|
+
* cubic on a layout with no rows to go round by. */
|
|
2047
2055
|
function edge_type_for(gobj)
|
|
2048
2056
|
{
|
|
2049
2057
|
let lr = (layout_direction(gobj) === "LR");
|
|
2050
2058
|
let rowless = gobj_read_attr(gobj, "rowless_layouts") || [];
|
|
2051
|
-
|
|
2052
|
-
|
|
2059
|
+
let rows = !str_in_list(rowless, gobj.priv.layout);
|
|
2060
|
+
if(rows && gobj_read_str_attr(gobj, "edge_shape") === "elbow") {
|
|
2053
2061
|
return lr? "treedb-elbow-h" : "treedb-elbow-v";
|
|
2054
2062
|
}
|
|
2063
|
+
if(rows) {
|
|
2064
|
+
return lr? "treedb-curve-h" : "treedb-curve-v";
|
|
2065
|
+
}
|
|
2055
2066
|
return lr? "cubic-horizontal" : "cubic";
|
|
2056
2067
|
}
|
|
2057
2068
|
|
|
@@ -4388,6 +4399,51 @@ class TreedbElbowH extends Polyline
|
|
|
4388
4399
|
}
|
|
4389
4400
|
}
|
|
4390
4401
|
|
|
4402
|
+
/************************************************************
|
|
4403
|
+
* A CURVED edge that keeps off the cards. G6's cubic, as before,
|
|
4404
|
+
* unless that very curve -- sampled, not guessed from the
|
|
4405
|
+
* rectangle round it -- would cross a card other than its own two,
|
|
4406
|
+
* or when it does not run forward and so would cross its own:
|
|
4407
|
+
* the card above a lower row of a stack, a row between a parent
|
|
4408
|
+
* and a far child. Then it goes the way an elbow would (the comb,
|
|
4409
|
+
* the detour, the route: the same lanes and staggered turns) with
|
|
4410
|
+
* round corners, so it still reads as a curve. `-v` for rows
|
|
4411
|
+
* stacked top to bottom, `-h` for columns.
|
|
4412
|
+
************************************************************/
|
|
4413
|
+
function curve_key_path(edge, attributes, vertical, plain)
|
|
4414
|
+
{
|
|
4415
|
+
let [s, t] = edge.getEndpoints(attributes, false);
|
|
4416
|
+
let along = vertical? 1 : 0;
|
|
4417
|
+
let box_s = elbow_box(edge.sourceNode);
|
|
4418
|
+
let box_t = elbow_box(edge.targetNode);
|
|
4419
|
+
let boxes = elbow_obstacles(edge);
|
|
4420
|
+
/* An edge that does not run forward -- one of every reciprocal
|
|
4421
|
+
* pair, an edge within one row -- runs through its OWN two cards
|
|
4422
|
+
* as a cubic, which curve_hits does not look at: it goes round
|
|
4423
|
+
* them, as its elbow does. */
|
|
4424
|
+
let forward = (t[along] - s[along] > 2 * ELBOW_STEP);
|
|
4425
|
+
if(forward && !curve_hits(plain, boxes, box_s, box_t)) {
|
|
4426
|
+
return plain;
|
|
4427
|
+
}
|
|
4428
|
+
let pts = elbow_route(s, t, box_s, box_t, elbow_lane_of(edge), vertical, boxes,
|
|
4429
|
+
elbow_stagger_of(edge, vertical));
|
|
4430
|
+
return rounded_path([s, ...pts, t], CURVE_RADIUS);
|
|
4431
|
+
}
|
|
4432
|
+
|
|
4433
|
+
class TreedbCurveV extends Cubic
|
|
4434
|
+
{
|
|
4435
|
+
getKeyPath(attributes) {
|
|
4436
|
+
return curve_key_path(this, attributes, true, super.getKeyPath(attributes));
|
|
4437
|
+
}
|
|
4438
|
+
}
|
|
4439
|
+
|
|
4440
|
+
class TreedbCurveH extends CubicHorizontal
|
|
4441
|
+
{
|
|
4442
|
+
getKeyPath(attributes) {
|
|
4443
|
+
return curve_key_path(this, attributes, false, super.getKeyPath(attributes));
|
|
4444
|
+
}
|
|
4445
|
+
}
|
|
4446
|
+
|
|
4391
4447
|
class TreedbCompactLayout extends BaseLayout
|
|
4392
4448
|
{
|
|
4393
4449
|
async execute(data, options) {
|