code wiki / _hdl_build / nx_viz_chord_page.nx

nx_viz_chord_page.nx source

↩ module page · 152 lines · 8288 B

1// nx_viz_chord_page.nx -- COMPOSED live CHORD diagram: parse a flow-matrix TSV (label + row per line), lay out 2// with nx_viz_chord (group arcs + sub-arcs), draw chords (quadratic curves through the centre) UNDER group bands 3// (stroked arcs), coloured per group (nx_viz_color), via nx_viz_trig for angle->point. Self-contained HTML for 4// the wiki. usage: nx_viz_chord_page [in.tsv] [out.html]. license_tier: ORIGINAL 5import "nx_viz_chord.nx" 6import "nx_viz_shape.nx" 7import "nx_viz_color.nx" 8import "nx_syscalls.nx" 9const K_MAGIC_10000: i64 = 10000 10const K_MAGIC_2048: i64 = 2048 11const K_MAGIC_262144: i64 = 262144 12const K_MAGIC_18000: i64 = 18000 13 14func cw(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 } 15func emit_hex6(out: *u8, off: i64, color: i64) -> i64 { 16 var o: i64 = off; out[o] = 35 as u8; o = o + 1 17 var sh: i64 = 20 18 while sh >= 0 { 19 let nib: i64 = (color >> sh) & 15 20 var ch: i64 = 48 + nib 21 if nib >= 10 { ch = 87 + nib } 22 out[o] = ch as u8; o = o + 1 23 sh = sh - 4 24 } 25 return o 26} 27func atoi_rng(buf: *u8, s: i64, e: i64) -> i64 { 28 var v: i64 = 0; var k: i64 = s 29 while k < e { let d: i64 = buf[k] as i64; if d >= 48 { if d <= 57 { v = v * 10 + (d - 48) } } k = k + 1 } 30 return v 31} 32func pt_x(cx: i64, r: i64, centideg: i64) -> i64 { return cx + (r * vs_cos(centideg / 100)) / K_MAGIC_10000 } 33func pt_y(cy: i64, r: i64, centideg: i64) -> i64 { return cy + (r * vs_sin(centideg / 100)) / K_MAGIC_10000 } 34 35func main(argc: i64, argv: *i64) -> i64 { 36 var inp: *u8 = "knowledge/registry/viz_tier_flow.tsv" as *u8 37 var outp: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/web_assets/viz_chord.html" as *u8 38 if argc >= 2 { inp = argv[1] as *u8 } 39 if argc >= 3 { outp = argv[2] as *u8 } 40 41 let lenp: *i64 = sys_mmap(16) as *i64 42 let buf: *u8 = sys_read_file(inp, lenp) 43 if (buf as i64) == 0 { cw(2, "nx_viz_chord_page: cannot read matrix\n" as *u8); return 2 } 44 let n: i64 = lenp[0] 45 46 let m16: *i64 = sys_mmap(K_MAGIC_2048) as *i64 47 let lab_off: *i64 = sys_mmap(512) as *i64 48 let lab_len: *i64 = sys_mmap(512) as *i64 49 var nc: i64 = 0 50 var i: i64 = 0 51 while i < n { 52 let ls: i64 = i 53 var le: i64 = ls 54 while le < n { if buf[le] == (10 as u8) { break } le = le + 1 } 55 if le > ls { 56 if buf[ls] != (35 as u8) { 57 var t1: i64 = ls 58 while t1 < le { if buf[t1] == (9 as u8) { break } t1 = t1 + 1 } 59 if t1 < le { 60 lab_off[nc] = ls; lab_len[nc] = t1 - ls 61 var vstart: i64 = t1 + 1; var c: i64 = 0 62 while vstart < le { 63 var vend: i64 = vstart 64 while vend < le { if buf[vend] == (9 as u8) { break } vend = vend + 1 } 65 m16[nc * 16 + c] = atoi_rng(buf, vstart, vend) 66 c = c + 1 67 vstart = vend + 1 68 } 69 nc = nc + 1 70 } 71 } 72 } 73 i = le + 1 74 } 75 if nc == 0 { cw(2, "nx_viz_chord_page: no rows\n" as *u8); return 3 } 76 77 let matrix: *i64 = sys_mmap(K_MAGIC_2048) as *i64 78 var r: i64 = 0 79 while r < nc { var c: i64 = 0; while c < nc { matrix[r * nc + c] = m16[r * 16 + c]; c = c + 1 } r = r + 1 } 80 81 let garc: *i64 = sys_mmap(512) as *i64 82 vch_groups(matrix, nc, garc) 83 84 let W: i64 = 720 85 let cx: i64 = 360 86 let cy: i64 = 360 87 let R: i64 = 286 88 let BAND: i64 = 22 89 let RC: i64 = R - BAND 90 91 let ob: *u8 = sys_mmap(K_MAGIC_262144) 92 var o: i64 = 0 93 o = vsh_lit(ob, o, "<!DOCTYPE html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Nishi Viz &mdash; Chord</title>" as *u8) 94 o = vsh_lit(ob, o, "<style>body{margin:0;background:#0d1117;color:#e6edf3;font-family:system-ui,-apple-system,sans-serif;padding:28px}h1{font-size:20px;margin:0 0 6px}p{color:#9aa4b2;max-width:820px;line-height:1.55}code{color:#79c0ff}a{color:#58a6ff;text-decoration:none}.card{margin-top:18px;background:#161b22;border:1px solid #30363d;border-radius:10px;padding:12px;display:inline-block}</style></head><body>" as *u8) 95 o = vsh_lit(ob, o, "<h1>Nishi Visualization Suite &mdash; chord diagram</h1>" as *u8) 96 o = vsh_lit(ob, o, "<p>Viz tiers as a flow matrix (diagonal = organs in the tier; off-diagonal = import flows), laid out by <code>nx_viz_chord</code> (arc proportional to row-sum) &mdash; group bands are stroked arcs, chords are curves through the centre, angle&rarr;point via <code>nx_viz_trig</code>, colour per tier. No d3.js, no CDN.</p>" as *u8) 97 o = vsh_lit(ob, o, "<div class=\"card\"><svg xmlns=\"http://www.w3.org/2000/svg\" width=\"" as *u8) 98 o = vsh_n(ob, o, W); o = vsh_lit(ob, o, "\" height=\"" as *u8); o = vsh_n(ob, o, W); o = vsh_lit(ob, o, "\" font-family=\"system-ui,sans-serif\">" as *u8) 99 100 // chords (under the bands) 101 var a: i64 = 0 102 while a < nc { 103 var b: i64 = 0 104 while b < nc { 105 if a != b { 106 if matrix[a * nc + b] > 0 { 107 let ai: i64 = vch_sub_mid(matrix, nc, a, b, garc) 108 let aj: i64 = vch_sub_mid(matrix, nc, b, a, garc) 109 let x0: i64 = pt_x(cx, RC, ai); let y0: i64 = pt_y(cy, RC, ai) 110 let x1: i64 = pt_x(cx, RC, aj); let y1: i64 = pt_y(cy, RC, aj) 111 o = vsh_lit(ob, o, "<path d=\"M " as *u8); o = vsh_n(ob, o, x0); o = vsh_lit(ob, o, " " as *u8); o = vsh_n(ob, o, y0) 112 o = vsh_lit(ob, o, " Q " as *u8); o = vsh_n(ob, o, cx); o = vsh_lit(ob, o, " " as *u8); o = vsh_n(ob, o, cy) 113 o = vsh_lit(ob, o, " " as *u8); o = vsh_n(ob, o, x1); o = vsh_lit(ob, o, " " as *u8); o = vsh_n(ob, o, y1) 114 o = vsh_lit(ob, o, "\" stroke=\"" as *u8); o = emit_hex6(ob, o, vc_categorical(a, nc)) 115 o = vsh_lit(ob, o, "\" stroke-width=\"2\" fill=\"none\" stroke-opacity=\"0.5\"/>" as *u8) 116 } 117 } 118 b = b + 1 119 } 120 a = a + 1 121 } 122 // group bands + labels 123 var g: i64 = 0 124 while g < nc { 125 let a0: i64 = garc[g * 2]; let a1: i64 = garc[g * 2 + 1] 126 let x0: i64 = pt_x(cx, R, a0); let y0: i64 = pt_y(cy, R, a0) 127 let x1: i64 = pt_x(cx, R, a1); let y1: i64 = pt_y(cy, R, a1) 128 var large: i64 = 0; if a1 - a0 > K_MAGIC_18000 { large = 1 } 129 o = vsh_lit(ob, o, "<path d=\"M " as *u8); o = vsh_n(ob, o, x0); o = vsh_lit(ob, o, " " as *u8); o = vsh_n(ob, o, y0) 130 o = vsh_lit(ob, o, " A " as *u8); o = vsh_n(ob, o, R); o = vsh_lit(ob, o, " " as *u8); o = vsh_n(ob, o, R); o = vsh_lit(ob, o, " 0 " as *u8); o = vsh_n(ob, o, large); o = vsh_lit(ob, o, " 1 " as *u8) 131 o = vsh_n(ob, o, x1); o = vsh_lit(ob, o, " " as *u8); o = vsh_n(ob, o, y1) 132 o = vsh_lit(ob, o, "\" stroke=\"" as *u8); o = emit_hex6(ob, o, vc_categorical(g, nc)); o = vsh_lit(ob, o, "\" stroke-width=\"22\" fill=\"none\"/>" as *u8) 133 let amid: i64 = (a0 + a1) / 2 134 let lx: i64 = pt_x(cx, R + 20, amid); let ly: i64 = pt_y(cy, R + 20, amid) 135 o = vsh_lit(ob, o, "<text x=\"" as *u8); o = vsh_n(ob, o, lx); o = vsh_lit(ob, o, "\" y=\"" as *u8); o = vsh_n(ob, o, ly) 136 o = vsh_lit(ob, o, "\" text-anchor=\"middle\" font-size=\"13\" fill=\"#e6edf3\">" as *u8) 137 var lk: i64 = lab_off[g]; let lend: i64 = lab_off[g] + lab_len[g] 138 while lk < lend { ob[o] = buf[lk]; o = o + 1; lk = lk + 1 } 139 o = vsh_lit(ob, o, "</text>" as *u8) 140 g = g + 1 141 } 142 o = vsh_lit(ob, o, "</svg></div>" as *u8) 143 o = vsh_lit(ob, o, "<p style=\"margin-top:16px;font-size:13px\">Generated by <code>nx_viz_chord_page</code> from <code>viz_tier_flow.tsv</code>. &nbsp;<a href=\"viz-graph.html\">&larr; module graph</a> &middot; <a href=\"viz-icicle.html\">icicle</a></p>" as *u8) 144 o = vsh_lit(ob, o, "</body></html>" as *u8) 145 146 let fd: i64 = sys_openat_wr(outp, 0x1a4) 147 if fd < 0 { cw(2, "nx_viz_chord_page: cannot open output\n" as *u8); return 5 } 148 sys_write(fd, ob, o) 149 sys_close(fd) 150 cw(1, "[nx_viz_chord_page] wrote " as *u8); cw(1, outp); cw(1, "\n" as *u8) 151 return 0 152}