From 771dcb13aed8795ecb1eee7308411770ae37c25c Mon Sep 17 00:00:00 2001 From: Andrew Stein Date: Tue, 26 Oct 2021 01:56:53 -0400 Subject: [PATCH] Add ExprTK example `fractal` --- examples/blocks/gists.json | 3 +- examples/blocks/src/fractal/.block | 2 + examples/blocks/src/fractal/README.md | 3 + examples/blocks/src/fractal/index.css | 107 +++++++ examples/blocks/src/fractal/index.html | 42 +++ examples/blocks/src/fractal/index.js | 158 ++++++++++ examples/blocks/src/mandelbrot/index.html | 341 ---------------------- 7 files changed, 314 insertions(+), 342 deletions(-) create mode 100644 examples/blocks/src/fractal/.block create mode 100644 examples/blocks/src/fractal/README.md create mode 100644 examples/blocks/src/fractal/index.css create mode 100644 examples/blocks/src/fractal/index.html create mode 100644 examples/blocks/src/fractal/index.js delete mode 100644 examples/blocks/src/mandelbrot/index.html diff --git a/examples/blocks/gists.json b/examples/blocks/gists.json index a1e528c23c..9d7617b6e6 100644 --- a/examples/blocks/gists.json +++ b/examples/blocks/gists.json @@ -7,5 +7,6 @@ "csv": "02d8fd10aef21b19d6165cf92e43e668", "iex": "eb151fdd9f98bde987538cbc20e003f6", "citibike": "bc8d7e6f72e09c9dbd7424b4332cacad", - "movies": "6b4dcebf65db4ebe4fe53a6de5ea0b48" + "movies": "6b4dcebf65db4ebe4fe53a6de5ea0b48", + "fractal": "5485f6b630b08d38218822e507f09f21" } \ No newline at end of file diff --git a/examples/blocks/src/fractal/.block b/examples/blocks/src/fractal/.block new file mode 100644 index 0000000000..37ce96a73a --- /dev/null +++ b/examples/blocks/src/fractal/.block @@ -0,0 +1,2 @@ +license: apache-2.0 +height: 800 \ No newline at end of file diff --git a/examples/blocks/src/fractal/README.md b/examples/blocks/src/fractal/README.md new file mode 100644 index 0000000000..7ca1777a9c --- /dev/null +++ b/examples/blocks/src/fractal/README.md @@ -0,0 +1,3 @@ +Demo of [Perspective](https://github.com/finos/perspective). + +A classic [fractal](https://en.wikipedia.org/wiki/Mandelbrot_set) implemented entirely in ExprTK/Perspective. diff --git a/examples/blocks/src/fractal/index.css b/examples/blocks/src/fractal/index.css new file mode 100644 index 0000000000..97085f7154 --- /dev/null +++ b/examples/blocks/src/fractal/index.css @@ -0,0 +1,107 @@ +perspective-viewer { + flex: 1; + margin: 24px; + overflow: visible; + --d3fc-positive--gradient: linear-gradient( + #94d0ff, + #8795e8, + #966bff, + #ad8cff, + #c774e8, + #c774a9, + #ff6ad5, + #ff6a8b, + #ff8b8b, + #ffa58b, + #ffde8b, + #cdde8b, + #8bde8b, + #20de8b + ); +} + +#app { + display: flex; + flex-direction: column; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #f2f4f6; +} + +#controls { + display: flex; + margin: 24px 24px 0px 40px; +} + +.range { + position: relative; + display: inline-flex; + flex-direction: column; + margin-right: 24px; +} + +span, +input, +button { + font-family: "Open Sans"; + font-size: 12px; + background: none; + margin: 0px; + border-color: #ccc; + color: #666; + padding: 6px 12px 6px 0px; +} + +input { + height: 14px; + border-width: 0px; + border-style: solid; + border-bottom-width: 1px; + color: inherit; + outline: none; +} + +input[type="range"] { + margin-top: 2px; +} + +input[type="number"] { + font-family: "Roboto Mono"; +} + +input:focus { + border-color: #1a7da1; +} + +input::placeholder { + color: #ccc; +} + +button { + border: 1px solid #ccc; + text-transform: uppercase; + text-align: center; + text-decoration: none; + display: inline-block; + padding-left: 12px; + height: 28px; + outline: none; +} + +button:hover { + cursor: pointer; +} + +#run { + justify-self: center; + margin-right: 24px; + height: 83px; + width: 80px; +} + +#run:disabled { + opacity: 0.2; +} diff --git a/examples/blocks/src/fractal/index.html b/examples/blocks/src/fractal/index.html new file mode 100644 index 0000000000..19f907d21b --- /dev/null +++ b/examples/blocks/src/fractal/index.html @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + +
+
+ +
+ Size + + +
+
+ X [-0.4 , -0.3] + + +
+
+ Y [-0.7 , -0.6] + + +
+
+ Iterations + +
+
+ +
+ + + \ No newline at end of file diff --git a/examples/blocks/src/fractal/index.js b/examples/blocks/src/fractal/index.js new file mode 100644 index 0000000000..93b158d8d3 --- /dev/null +++ b/examples/blocks/src/fractal/index.js @@ -0,0 +1,158 @@ +function generate_mandelbrot(params) { + return ` +// color +var height := ${params.height}; +var width := ${params.width}; +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 c := iterations; + +var cx := xmin + ((xmax - xmin) * x) / (width - 1); +var cy := ymin + ((ymax - ymin) * y) / (height - 1); + +var vx := 0; +var vy := 0; +var vxx := 0; +var vyy := 0; +var vxy := 0; + +for (var ii := 0; ii < iterations; ii += 1) { + if (vxx + vyy <= float(4)) { + vxy := vx * vy; + vxx := vx * vx; + vyy := vy * vy; + vx := vxx - vyy + cx; + vy := vxy + vxy + cy; + c -= 1; + } +}; + +c`; +} + +function generate_layout(params) { + return { + plugin: "Heatmap", + settings: true, + row_pivots: [`floor("index" / ${params.height})`], + column_pivots: [`"index" % ${params.height}`], + columns: ["color"], + expressions: [ + generate_mandelbrot(params).trim(), + `floor("index" / ${params.height})`, + `"index" % ${params.height}`, + ], + }; +} + +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; + json[index] = { + index, + }; + } + } + + await table.replace(json); + run.innerHTML = `Run`; +} + +// GUI + +function get_gui_params() { + return [ + "xmin", + "xmax", + "ymin", + "ymax", + "width", + "height", + "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) + + "]"; + + 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(); + }); +} + +const make_run_click_callback = (worker, state) => async () => { + if (window.run.innerHTML.trim() !== "Run") { + window.run.innerHTML = "Run"; + return; + } + + window.run.disabled = true; + if (!state.table) { + state.table = await worker.table({ + index: "integer", + }); + window.viewer.load(Promise.resolve(state.table)); + } + + const run = document.getElementById("run"); + const params = get_gui_params(); + const new_size = params.width * params.height; + if (!state.size || state.size !== new_size) { + let json = {index: new Array(new_size)}; + for (let x = 0; x < new_size; ++x) { + json.index[x] = x; + } + + state.table.replace(json); + } + + state.size = new_size; + run.innerHTML = `Run`; + window.viewer.restore(generate_layout(params)); +}; + +function set_runnable() { + window.run.disabled = false; +} + +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); + window.iterations.addEventListener("input", set_runnable); + + run.addEventListener( + "click", + make_run_click_callback(window.perspective.worker(), {}) + ); + run.dispatchEvent(new Event("click")); +}); diff --git a/examples/blocks/src/mandelbrot/index.html b/examples/blocks/src/mandelbrot/index.html deleted file mode 100644 index 26187d43b4..0000000000 --- a/examples/blocks/src/mandelbrot/index.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- Size - - -
-
- X [-0.4 , -0.1] - - -
-
- Y [-0.7 , -0.6] - - -
-
- Iterations - - -
-
- Theme - -
-
- - - -
- - - - - - \ No newline at end of file