diff --git a/README.md b/README.md index 25523f6d05..0758566dd1 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ and/or [Jupyterlab](https://jupyterlab.readthedocs.io/en/stable/). ### Examples -
editablefilefractal
marketraycastingevictions
nypdmagicstreaming
covidmoviessuperstore
citibikeolympicsjupyterlab
+
editablefilefractal
marketraycastingevictions
nypdmagicstreaming
covidmoviessuperstore
citibikeolympicsjupyterlab
### Documentation diff --git a/docs/static/img/jupyterlab.png b/docs/static/img/jupyterlab.png index 47bb19840c..39eeb7a58b 100644 Binary files a/docs/static/img/jupyterlab.png and b/docs/static/img/jupyterlab.png differ diff --git a/examples/blocks/examples.js b/examples/blocks/examples.js index b2010c1f59..cba1710237 100644 --- a/examples/blocks/examples.js +++ b/examples/blocks/examples.js @@ -34,15 +34,16 @@ exports.get_examples = function get_examples( ) { const standalone = [ { - img: "https://perspective.finos.org/img/jupyterlab.png", + img: "https://perspective.finos.org/img/jupyterlab.png?", url: "http://beta.mybinder.org/v2/gh/finos/perspective/master?urlpath=lab/tree/examples/jupyter-notebooks", name: "jupyterlab", }, ]; const hashes = LOCAL_EXAMPLES.map((x) => ({ - img: `${root}blocks/${x}/preview.png`, + img: `${root}blocks/${x}/preview.png?`, url: `${root}block?example=${x}`, + name: x, })); diff --git a/examples/blocks/src/citibike/preview.png b/examples/blocks/src/citibike/preview.png index 9dcce0bc22..4b0944cdf1 100644 Binary files a/examples/blocks/src/citibike/preview.png and b/examples/blocks/src/citibike/preview.png differ diff --git a/examples/blocks/src/citibike/thumbnail.png b/examples/blocks/src/citibike/thumbnail.png index f3e96fbe45..15c3b5c339 100644 Binary files a/examples/blocks/src/citibike/thumbnail.png and b/examples/blocks/src/citibike/thumbnail.png differ diff --git a/examples/blocks/src/covid/preview.png b/examples/blocks/src/covid/preview.png index 56da7ff633..eec01e5a3c 100644 Binary files a/examples/blocks/src/covid/preview.png and b/examples/blocks/src/covid/preview.png differ diff --git a/examples/blocks/src/covid/thumbnail.png b/examples/blocks/src/covid/thumbnail.png index ab29919ceb..5e1830c74a 100644 Binary files a/examples/blocks/src/covid/thumbnail.png and b/examples/blocks/src/covid/thumbnail.png differ diff --git a/examples/blocks/src/editable/preview.png b/examples/blocks/src/editable/preview.png index 08e41f68d5..c9c1e69784 100644 Binary files a/examples/blocks/src/editable/preview.png and b/examples/blocks/src/editable/preview.png differ diff --git a/examples/blocks/src/editable/thumbnail.png b/examples/blocks/src/editable/thumbnail.png index f1bcd2d955..c6ed927565 100644 Binary files a/examples/blocks/src/editable/thumbnail.png and b/examples/blocks/src/editable/thumbnail.png differ diff --git a/examples/blocks/src/evictions/preview.png b/examples/blocks/src/evictions/preview.png index 14588f9d42..bdfc9cbee2 100644 Binary files a/examples/blocks/src/evictions/preview.png and b/examples/blocks/src/evictions/preview.png differ diff --git a/examples/blocks/src/evictions/thumbnail.png b/examples/blocks/src/evictions/thumbnail.png index 46a711a166..cddfb13a38 100644 Binary files a/examples/blocks/src/evictions/thumbnail.png and b/examples/blocks/src/evictions/thumbnail.png differ diff --git a/examples/blocks/src/fractal/index.css b/examples/blocks/src/fractal/index.css index 58302bf6c9..de4f451c30 100644 --- a/examples/blocks/src/fractal/index.css +++ b/examples/blocks/src/fractal/index.css @@ -13,8 +13,8 @@ perspective-viewer { flex: 1; - margin: 24px; overflow: visible; + margin-left: 60px; } perspective-viewer[theme="Pro Light"], @@ -50,7 +50,16 @@ perspective-viewer[theme="Pro Dark"] { #controls { display: flex; - margin: 24px 24px 0px 40px; + /* padding: 12px; */ + border-bottom: 1px solid #ababab; +} + +#controls2 { + position: absolute; + left: 0; + width: 60px; + bottom: 0; + top: 40px; } .range { @@ -60,6 +69,14 @@ perspective-viewer[theme="Pro Dark"] { margin-right: 24px; } +.range.xl { + width: 200px; +} + +.range.right { + float: right; +} + span, input, button { @@ -72,17 +89,17 @@ button { padding: 6px 12px 6px 0px; } +span { + font-size: 10px; +} + input { - height: 14px; border-width: 0px; border-style: solid; border-bottom-width: 1px; color: inherit; outline: none; -} - -input[type="range"] { - margin-top: 2px; + padding: 0px; } input[type="number"] { @@ -98,7 +115,8 @@ input::placeholder { } button { - border: 1px solid #ccc; + border: 0px solid #ccc; + border-right-width: 1px; text-transform: uppercase; text-align: center; text-decoration: none; @@ -115,10 +133,82 @@ button:hover { #run { justify-self: center; margin-right: 24px; - height: 83px; - width: 80px; + height: 50px; + width: 60px; } #run:disabled { - opacity: 0.2; + /* opacity: 0.2; */ + color: #ccc; +} + +input[type="range"]::-webkit-slider-thumb { + -webkit-appearance: none; + pointer-events: all; + width: 6px; + height: 24px; + background-color: #fff; + border-radius: 0px; + box-shadow: 0 0 0 1px #c6c6c6; + cursor: pointer; +} + +input[type="range"]::-moz-range-thumb { + -webkit-appearance: none; + pointer-events: all; + width: 6px; + height: 24px; + background-color: #fff; + border-radius: 0px; + box-shadow: 0 0 0 1px #c6c6c6; + cursor: pointer; +} + +input[type="range"]::-webkit-slider-thumb:hover { + background: #f7f7f7; +} + +input[type="range"]::-webkit-slider-thumb:active { + box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe; + -webkit-box-shadow: inset 0 0 3px #387bbe, 0 0 9px #387bbe; +} +/* +input[type="number"] { + color: #8a8383; + width: 50px; + height: 30px; + font-size: 20px; + border: none; +} */ +/* +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + opacity: 1; +} */ + +input[type="range"] { + -webkit-appearance: none; + appearance: none; + height: 2px; + width: 100%; + position: absolute; + background-color: #c6c6c6; + pointer-events: none; + padding: 0; + top: 25px; + width: 200px; +} + +#ymin, +#xmin { + z-index: 1; +} + +#ymin, +#ymax { + /* -webkit-appearance: slider-vertical; */ + transform: rotate(-90deg); + transform-origin: top left; + top: 220px; + left: 30px; } diff --git a/examples/blocks/src/fractal/index.html b/examples/blocks/src/fractal/index.html index c860685fd9..a27f7359fa 100644 --- a/examples/blocks/src/fractal/index.html +++ b/examples/blocks/src/fractal/index.html @@ -14,26 +14,25 @@
-
- Size - - -
-
- X [-0.4 , -0.3] +
-
- Y [-0.7 , -0.6] - - +
+ Resolution +
-
+
Iterations
+
+
+ + +
+
diff --git a/examples/blocks/src/fractal/index.js b/examples/blocks/src/fractal/index.js index 5953269aa4..40c1989d06 100644 --- a/examples/blocks/src/fractal/index.js +++ b/examples/blocks/src/fractal/index.js @@ -15,20 +15,19 @@ import perspective from "/node_modules/@finos/perspective/dist/cdn/perspective.j function generate_mandelbrot(params) { return ` // color -var height := ${params.height}; -var width := ${params.width}; +var resolution := ${params.resolution}; var xmin := ${params.xmin}; var xmax := ${params.xmax}; var ymin := ${params.ymin}; var ymax := ${params.ymax}; var iterations := ${params.iterations}; -var x := floor("index" / height); -var y := "index" % height; +var x := floor("index" / resolution); +var y := "index" % resolution; var c := iterations; -var cx := xmin + ((xmax - xmin) * x) / (width - 1); -var cy := ymin + ((ymax - ymin) * y) / (height - 1); +var cx := xmin + ((xmax - xmin) * x) / (resolution - 1); +var cy := ymin + ((ymax - ymin) * y) / (resolution - 1); var vx := 0; var vy := 0; @@ -54,23 +53,23 @@ function generate_layout(params) { return { plugin: "Heatmap", settings: true, - group_by: [`floor("index" / ${params.height})`], - split_by: [`"index" % ${params.height}`], + group_by: [`floor("index" / ${params.resolution})`], + split_by: [`"index" % ${params.resolution}`], columns: ["color"], expressions: [ generate_mandelbrot(params).trim(), - `floor("index" / ${params.height})`, - `"index" % ${params.height}`, + `floor("index" / ${params.resolution})`, + `"index" % ${params.resolution}`, ], }; } async function generate_data(table) { const run = document.getElementById("run"); - let json = new Array(width * height); - for (let x = 0; x < width; ++x) { - for (let y = 0; y < height; ++y) { - const index = x * height + y; + let json = new Array(Math.pow(resolution, 2)); + for (let x = 0; x < resolution; ++x) { + for (let y = 0; y < resolution; ++y) { + const index = x * resolution + y; json[index] = { index, }; @@ -84,39 +83,24 @@ async function generate_data(table) { // GUI function get_gui_params() { - return [ - "xmin", - "xmax", - "ymin", - "ymax", - "width", - "height", - "iterations", - ].reduce((acc, x) => { - acc[x] = window[x].valueAsNumber; - return acc; - }, {}); + return ["xmin", "xmax", "ymin", "ymax", "resolution", "iterations"].reduce( + (acc, x) => { + acc[x] = window[x].valueAsNumber; + return acc; + }, + {} + ); } -function make_range(x, y, range, name) { - const title = () => - name + - " [" + - x.valueAsNumber.toFixed(1) + - ", " + - y.valueAsNumber.toFixed(1) + - "]"; - +function make_range(x, y, name) { x.addEventListener("input", () => { window.run.disabled = false; x.value = Math.min(x.valueAsNumber, y.valueAsNumber - 0.1); - range.innerHTML = title(); }); y.addEventListener("input", () => { window.run.disabled = false; y.value = Math.max(x.valueAsNumber + 0.1, y.valueAsNumber); - range.innerHTML = title(); }); } @@ -136,7 +120,7 @@ const make_run_click_callback = (worker, state) => async () => { const run = document.getElementById("run"); const params = get_gui_params(); - const new_size = params.width * params.height; + const new_size = Math.pow(params.resolution, 2); if (!state.size || state.size !== new_size) { let json = { index: new Array(new_size) }; for (let x = 0; x < new_size; ++x) { @@ -158,10 +142,9 @@ function set_runnable() { window.addEventListener("DOMContentLoaded", async function () { const heatmap_plugin = await window.viewer.getPlugin("Heatmap"); heatmap_plugin.max_cells = 100000; - make_range(xmin, xmax, xrange, "X"); - make_range(ymin, ymax, yrange, "Y"); - window.width.addEventListener("input", set_runnable); - window.height.addEventListener("input", set_runnable); + make_range(xmin, xmax, "X"); + make_range(ymin, ymax, "Y"); + window.resolution.addEventListener("input", set_runnable); window.iterations.addEventListener("input", set_runnable); run.addEventListener( diff --git a/examples/blocks/src/fractal/preview.png b/examples/blocks/src/fractal/preview.png index 45a388c146..9baec4fd26 100644 Binary files a/examples/blocks/src/fractal/preview.png and b/examples/blocks/src/fractal/preview.png differ diff --git a/examples/blocks/src/fractal/thumbnail.png b/examples/blocks/src/fractal/thumbnail.png index a3cab2655c..0b818bbf15 100644 Binary files a/examples/blocks/src/fractal/thumbnail.png and b/examples/blocks/src/fractal/thumbnail.png differ diff --git a/examples/blocks/src/market/preview.png b/examples/blocks/src/market/preview.png index b7aed3beab..124dad45c2 100644 Binary files a/examples/blocks/src/market/preview.png and b/examples/blocks/src/market/preview.png differ diff --git a/examples/blocks/src/market/thumbnail.png b/examples/blocks/src/market/thumbnail.png new file mode 100644 index 0000000000..b41b07dc06 Binary files /dev/null and b/examples/blocks/src/market/thumbnail.png differ diff --git a/examples/blocks/src/movies/preview.png b/examples/blocks/src/movies/preview.png index 3dfd67d836..0484fd67b1 100644 Binary files a/examples/blocks/src/movies/preview.png and b/examples/blocks/src/movies/preview.png differ diff --git a/examples/blocks/src/movies/thumbnail.png b/examples/blocks/src/movies/thumbnail.png index abc5d4b584..814c7153e2 100644 Binary files a/examples/blocks/src/movies/thumbnail.png and b/examples/blocks/src/movies/thumbnail.png differ diff --git a/examples/blocks/src/olympics/index.html b/examples/blocks/src/olympics/index.html index e1f17f2dc7..3a06f6d670 100644 --- a/examples/blocks/src/olympics/index.html +++ b/examples/blocks/src/olympics/index.html @@ -63,6 +63,7 @@ columns: ["Height", "Weight", null, "City", "Sport", null], filter: [["Height", "==", null]], sort: [["Name", "desc"]], + expressions: {}, aggregates: { Name: "distinct count", Weight: "avg", @@ -82,6 +83,7 @@ ["Age", "is not null", null], ], sort: [["Name", "col asc"]], + expressions: {}, aggregates: { Age: "avg", }, diff --git a/examples/blocks/src/olympics/preview.png b/examples/blocks/src/olympics/preview.png index 882bf63687..5cb91163a9 100644 Binary files a/examples/blocks/src/olympics/preview.png and b/examples/blocks/src/olympics/preview.png differ diff --git a/examples/blocks/src/olympics/thumbnail.png b/examples/blocks/src/olympics/thumbnail.png index 432558cb92..2f4b9d11f9 100644 Binary files a/examples/blocks/src/olympics/thumbnail.png and b/examples/blocks/src/olympics/thumbnail.png differ diff --git a/examples/blocks/src/raycasting/README.md b/examples/blocks/src/raycasting/README.md index 438148465e..d9731e2fa6 100644 --- a/examples/blocks/src/raycasting/README.md +++ b/examples/blocks/src/raycasting/README.md @@ -1,6 +1,6 @@ -A ray-tracing engine written as an [ExprTK](https://github.com/ArashPartow/exprtk) +A ray-casting engine written as an [ExprTK](https://github.com/ArashPartow/exprtk) Expression within [Perspective](https://github.com/finos/perspective). As presented at [Open Source in Finance 2022 NY](https://www.youtube.com/watch?v=0ut-ynvBpGI). -This example has no server component, and all ray-tracing is done entirely within the -Perspective WebAssembly engine. +This example has no server component, and all ray-casting is done entirely +within the Perspective WebAssembly engine. diff --git a/examples/blocks/src/raycasting/index.css b/examples/blocks/src/raycasting/index.css index 0b1e7671e7..58623eb21d 100644 --- a/examples/blocks/src/raycasting/index.css +++ b/examples/blocks/src/raycasting/index.css @@ -20,22 +20,22 @@ perspective-viewer { bottom: 0; } -perspective-viewer[theme="Pro Light"], perspective-viewer[theme="Pro Dark"] { --d3fc-positive--gradient: linear-gradient( - #94d0ff, - #8795e8, - #966bff, - #ad8cff, - #c774e8, - #c774a9, - #ff6ad5, - #ff6a8b, - #ff8b8b, - #ffa58b, - #ffde8b, - #cdde8b, - #8bde8b, - #20de8b + #242526, + #071952 1%, + #088395, + #35a29f, + #f2f7a1 + ); +} + +perspective-viewer[theme="Pro Light"] { + --d3fc-positive--gradient: linear-gradient( + #ffffff, + #071952 1%, + #088395, + #35a29f, + #f2f7a1 ); } diff --git a/examples/blocks/src/raycasting/index.js b/examples/blocks/src/raycasting/index.js index 2f04a9ce8d..8702afb1a2 100644 --- a/examples/blocks/src/raycasting/index.js +++ b/examples/blocks/src/raycasting/index.js @@ -12,136 +12,105 @@ import perspective from "/node_modules/@finos/perspective/dist/cdn/perspective.js"; -const WIDTH = 200; -const HEIGHT = 200; - -const vertices = [ - [-100, -100, -100], - [-100, -100, 100], - [-100, 100, 100], - - [100, 100, -100], - [-100, -100, -100], - [-100, 100, -100], - - [100, -100, 100], - [-100, -100, -100], - [100, -100, -100], - - [100, 100, -100], - [100, -100, -100], - [-100, -100, -100], - - [-100, -100, -100], - [-100, 100, 100], - [-100, 100, -100], - - [100, -100, 100], - [-100, -100, 100], - [-100, -100, -100], - - [-100, 100, 100], - [-100, -100, 100], - [100, -100, 100], - - [100, 100, 100], - [100, -100, -100], - [100, 100, -100], - - [100, -100, -100], - [100, 100, 100], - [100, -100, 100], - - [100, 100, 100], - [100, 100, -100], - [-100, 100, -100], - - [100, 100, 100], - [-100, 100, -100], - [-100, 100, 100], - - [100, 100, 100], - [-100, 100, 100], - [100, -100, 100], -]; - -const colors = [3, 1, 2, 1, 3, 2, 6, 4, 4, 5, 5, 6]; - -function generate_scene() { - let vertices2 = []; - let colors2 = []; - for (let i = 0; i < 50; i++) { - const x_offset = Math.random() * 2000 - 1000; - const y_offset = Math.random() * 2000 - 1000; - const z_offset = Math.random() * 2000; - for (const v in vertices) { - const vertex = structuredClone(vertices[v]); - vertex[0] += x_offset; - vertex[1] += y_offset; - vertex[2] += z_offset; - vertices2.push(vertex); - if (v % 3 === 0) { - colors2.push(colors[(v / 3) % colors.length]); - } - } +const RESOLUTION = 100; + +const EXPRESSION = ` +// Scene constants +var resolution := ${RESOLUTION}; +var fov := 30 * (pi / 180); +var camera[3] := {0, 0, -600}; +var light[3] := {0.5, 1, 0}; + +// Torus constants +var radius := 1; +var tube := 0.4; +var radialSegments := 12; +var tubularSegments := 16; +var rotation := 40 * (pi / 180); + +// Mesh +var arc := pi * 2; +var vs[663]; +for (var j := 0; j <= radialSegments; j += 1) { + for (var i := 0; i <= tubularSegments; i += 1) { + + // Vertex + var u := (i / tubularSegments) * arc; + var v := (j / radialSegments) * pi * 2; + var i0 := j * 3 * (tubularSegments + 1) + (i * 3); + vs[i0] := (radius + tube * cos(v)) * cos(u) * 100; + vs[i0 + 1] := (radius + tube * cos(v)) * sin(u) * 100; + vs[i0 + 2] := tube * sin(v) * 100; + + // Rotate + var b := vs[i0 + 1]; + var bcos := cos(rotation); + var bsin := sin(rotation); + vs[i0 + 1] := vs[i0 + 1] * bcos - vs[i0 + 2] * bsin; + vs[i0 + 2] := b * bsin + vs[i0 + 2] * bcos; + b := vs[i0]; + vs[i0] := vs[i0] * bcos - vs[i0 + 2] * bsin; + vs[i0 + 2] := b * bsin + vs[i0 + 2] * bcos; } - - return [vertices2, colors2]; } -function generate_mandelbrot() { - const [vertices2, colors2] = generate_scene(); - - return ` -// color -var d[3] := {floor("index" / ${HEIGHT}) - ${HEIGHT} / 2, "index" % ${HEIGHT} - ${HEIGHT} / 2, 50}; -var p[3] := {0, 0, -500}; - -var vs[9 * ${vertices2.flat().length / 9}] := {${vertices2.flat().join(", ")}}; -var cs[${colors2.flat().length}] := {${colors2.flat().join(", ")}}; +// Render scene +var scale := resolution / (tan(fov / 2) * 400); +var x := (floor(index() / resolution) - resolution / 2) / scale; +var y := (index() % resolution - resolution / 2) / scale; +var d[3] := {x, y, 200}; var color := 0; -var depth := 1000000; - -for (var i := 0; i < ${vertices2.flat().length / 9}; i += 1) { - var v0[3] := {vs[i * 9], vs[i * 9 + 1], vs[i * 9 + 2]}; - var v1[3] := {vs[i * 9 + 3], vs[i * 9 + 4], vs[i * 9 + 5]}; - var v2[3] := {vs[i * 9 + 6], vs[i * 9 + 7], vs[i * 9 + 8]}; - - var e1[3]; - diff3(v1, v0, e1); - var e2[3]; - diff3(v2, v0, e2); - - var h[3]; - cross_product3(d, e2, h); - var a := dot_product3(e1, h); - - if (a < -0.000001 or a > 0.000001) { - var f := 1 / a; - var s[3]; - diff3(p, v0, s); - var u := f * dot_product3(s, h); - - if (u > 0 and u < 1) { - var q[3]; - cross_product3(s, e1, q); - var v := f * dot_product3(d, q); - if (v > 0 and u + v < 1) { - var t := f * dot_product3(e2, q); - if (t > -0.0000001) { - var t2 := 1 - u - v; - var d1[3] := { - t2 * v0[0] + u * v1[0] + v * v2[0], - t2 * v0[1] + u * v1[1] + v * v2[1], - t2 * v0[2] + u * v1[2] + v * v2[2] - }; - - var d2[3]; - diff3(d1, p, d2); - var dist := norm3(d2); - if (dist < depth) { - depth := dist; - color := cs[i]; +var depth := inf; +var light_norm := norm3(light); +for (var j := 1; j <= radialSegments; j += 1) { + for (var i := 1; i <= tubularSegments; i += 1) { + + // Index + var aa := (tubularSegments + 1) * j + i - 1; + var b := (tubularSegments + 1) * (j - 1) + i - 1; + var c := (tubularSegments + 1) * (j - 1) + i; + var dd := (tubularSegments + 1) * j + i; + var face[6] := {aa, b, dd, b, c, dd}; + for (var ii:= 0; ii < 2; ii += 1) { + var i0 := face[ii * 3]; + var i1 := face[ii * 3 + 1]; + var i2 := face[ii * 3 + 2]; + var v0[3] := {vs[i0 * 3], vs[i0 * 3 + 1], vs[i0 * 3 + 2]}; + var v1[3] := {vs[i1 * 3], vs[i1 * 3 + 1], vs[i1 * 3 + 2]}; + var v2[3] := {vs[i2 * 3], vs[i2 * 3 + 1], vs[i2 * 3 + 2]}; + + // Render triangle + var e1[3] := v1 - v0; + var e2[3] := v2 - v0; + var h[3]; + cross_product3(d, e2, h); + var a := dot_product3(e1, h); + if (a != 0) { + var f := 1 / a; + var s[3] := camera - v0; + var u := f * dot_product3(s, h); + if (u > 0 and u < 1) { + var q[3]; + cross_product3(s, e1, q); + var v := f * dot_product3(d, q); + if (v > 0 and u + v < 1) { + var t := f * dot_product3(e2, q); + if (t >= 0) { + var t2 := 1 - u - v; + var d1[3] := v0 * t2 + v1 * u + v2 * v; + var d2[3] := d1 - camera; + var dist := norm3(d2); + if (dist < depth) { + depth := dist; + + // Lighting + var ww[3] := v0 - v1; + var zz[3] := v2 - v1; + var n[3]; + cross_product3(ww, zz, n); + color := acos(dot_product3(light, n) / (light_norm * norm3(n))) + } + } } } } @@ -149,47 +118,30 @@ for (var i := 0; i < ${vertices2.flat().length / 9}; i += 1) { } }; -color -`; -} - -function generate_layout() { - return { - plugin: "Heatmap", - settings: true, - group_by: [`floor("index" / ${HEIGHT}) - ${HEIGHT} / 2`], - split_by: [`"index" % ${HEIGHT} - ${HEIGHT} / 2`], - columns: ["color"], - expressions: [ - generate_mandelbrot().trim(), - `floor("index" / ${HEIGHT}) - ${HEIGHT} / 2`, - `"index" % ${HEIGHT} - ${HEIGHT} / 2`, - ], - }; -} - -async function generate_data(table) { - let json = new Array(WIDTH * HEIGHT); - for (let x = 0; x < WIDTH; ++x) { - for (let y = 0; y < HEIGHT; ++y) { - const index = x * HEIGHT + y; - json[index] = { - index, - }; - } - } - - await table.replace(json); -} +color; +`.trim(); + +const LAYOUT = { + title: "Raycasting", + plugin: "Heatmap", + group_by: [`x`], + split_by: [`y`], + columns: ["color"], + expressions: { + color: EXPRESSION, + x: `floor(index() / ${RESOLUTION}) - ${RESOLUTION} / 2`, + y: `index() % ${RESOLUTION} - ${RESOLUTION} / 2`, + }, + settings: true, + theme: "Pro Dark", +}; window.addEventListener("DOMContentLoaded", async function () { const heatmap_plugin = await window.viewer.getPlugin("Heatmap"); heatmap_plugin.max_cells = 100000; const worker = perspective.worker(); - const table = await worker.table({ - index: "integer", - }); - generate_data(table); - window.viewer.load(Promise.resolve(table)); - await window.viewer.restore(generate_layout()); + const index = new Array(Math.pow(RESOLUTION, 2)).fill(0); + const table = worker.table({ index }); + window.viewer.load(table); + await window.viewer.restore(LAYOUT); }); diff --git a/examples/blocks/src/raycasting/preview.png b/examples/blocks/src/raycasting/preview.png index 5ad8ef2206..19e17b54cc 100644 Binary files a/examples/blocks/src/raycasting/preview.png and b/examples/blocks/src/raycasting/preview.png differ diff --git a/examples/blocks/src/raycasting/thumbnail.png b/examples/blocks/src/raycasting/thumbnail.png index 405c1e84e0..08372f4a7e 100644 Binary files a/examples/blocks/src/raycasting/thumbnail.png and b/examples/blocks/src/raycasting/thumbnail.png differ diff --git a/examples/blocks/src/streaming/preview.png b/examples/blocks/src/streaming/preview.png index 68b19f9af1..f35984e4a3 100644 Binary files a/examples/blocks/src/streaming/preview.png and b/examples/blocks/src/streaming/preview.png differ diff --git a/examples/blocks/src/streaming/thumbnail.png b/examples/blocks/src/streaming/thumbnail.png index 959d2c5caa..7279282d3f 100644 Binary files a/examples/blocks/src/streaming/thumbnail.png and b/examples/blocks/src/streaming/thumbnail.png differ diff --git a/examples/blocks/src/superstore/preview.png b/examples/blocks/src/superstore/preview.png index b3777faccb..0aae565d2d 100644 Binary files a/examples/blocks/src/superstore/preview.png and b/examples/blocks/src/superstore/preview.png differ diff --git a/examples/blocks/src/superstore/thumbnail.png b/examples/blocks/src/superstore/thumbnail.png index e719c7e03d..f49194363d 100644 Binary files a/examples/blocks/src/superstore/thumbnail.png and b/examples/blocks/src/superstore/thumbnail.png differ