-
X [-0.4 , -0.3]
+
-
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