From d1ce91d2aa6f02706a11dd533daeb86ab8523f21 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Mon, 24 Jun 2024 19:37:57 -0700 Subject: [PATCH 1/9] Get a Ganja.js visualization running in Blink --- engine-proto/ganja-test/ganja-test.html | 51 ++++++++++++++++++ engine-proto/ganja-test/ganja-test.jl | 71 +++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 engine-proto/ganja-test/ganja-test.html create mode 100644 engine-proto/ganja-test/ganja-test.jl diff --git a/engine-proto/ganja-test/ganja-test.html b/engine-proto/ganja-test/ganja-test.html new file mode 100644 index 0000000..f1ecf45 --- /dev/null +++ b/engine-proto/ganja-test/ganja-test.html @@ -0,0 +1,51 @@ + + + + + + + + + + diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl new file mode 100644 index 0000000..ea8b334 --- /dev/null +++ b/engine-proto/ganja-test/ganja-test.jl @@ -0,0 +1,71 @@ +using Blink +import Blink: JSString + +# === styling utility === + +style!(w, stylesheet) = @js win begin + @var style = document.createElement("style"); + style.appendChild(document.createTextNode($stylesheet)); + document.head.appendChild(style); +end + +# === page source === + +stylesheet = """ +body { + background-color: #ffe0f0; +} + +/* needed to keep Ganja canvas from blowing up */ +canvas { + min-width: 600px; + max-width: 600px; + min-height: 600px; + max-height: 600px; +} +""" + +# the "points spheres plane" example from the Ganja coffee shop +# +# https://enkimute.github.io/ganja.js/examples/coffeeshop.html#cga3d_points_spheres_planes +# +sphere_example = """ +Algebra(4, 1, ()=>{ + // We start by defining a null basis, and upcasting for points + var ni = 1e4+1e5, no = .5e5-.5e4; + var up = (x)=> no + x + .5*x*x*ni; + + // Next we'll define 4 points + var p1 = up(1e1), p2 = up(1e2), p3 = up(-1e3), p4 = up(-1e2); + + // The outer product can be used to construct the sphere through + // any four points. + var s = ()=>p1^p2^p3^p4; + + // The outer product between any three points and infinity is a plane. + var p = ()=>p1^p2^p3^ni; + + // Graph the items. + document.body.appendChild(this.graph([ + 0x00FF0000, p1, "p1", p2, "p2", p3, "p3", p4, "p4", // points + 0xE0008800, p, "p", // plane + 0xE00000FF, s, "s" // sphere + ], {conformal: true, gl: true, grid: true})); +}); +""" + +# === page construction === + +# create window and open developer console +win = Window() +opentools(win) + +# set stylesheet +style!(win, stylesheet) + +# load Ganja.js +loadjs!(win, "https://unpkg.com/ganja.js") + +# launch Ganja visualization +body!(win, "", async=false) +js(win, JSString(sphere_example)) From 3c344815196a63cec0e5887239db65facbf77426 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 25 Jun 2024 01:54:01 -0700 Subject: [PATCH 2/9] Get familiar with Ganja.js inline syntax --- engine-proto/ganja-test/ganja-test.html | 50 ++++++++++++------------- engine-proto/ganja-test/ganja-test.jl | 46 ++++++++++++----------- 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/engine-proto/ganja-test/ganja-test.html b/engine-proto/ganja-test/ganja-test.html index f1ecf45..26eba9d 100644 --- a/engine-proto/ganja-test/ganja-test.html +++ b/engine-proto/ganja-test/ganja-test.html @@ -18,34 +18,30 @@ diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl index ea8b334..155caa9 100644 --- a/engine-proto/ganja-test/ganja-test.jl +++ b/engine-proto/ganja-test/ganja-test.jl @@ -30,28 +30,30 @@ canvas { # https://enkimute.github.io/ganja.js/examples/coffeeshop.html#cga3d_points_spheres_planes # sphere_example = """ -Algebra(4, 1, ()=>{ - // We start by defining a null basis, and upcasting for points - var ni = 1e4+1e5, no = .5e5-.5e4; - var up = (x)=> no + x + .5*x*x*ni; - - // Next we'll define 4 points - var p1 = up(1e1), p2 = up(1e2), p3 = up(-1e3), p4 = up(-1e2); - - // The outer product can be used to construct the sphere through - // any four points. - var s = ()=>p1^p2^p3^p4; - - // The outer product between any three points and infinity is a plane. - var p = ()=>p1^p2^p3^ni; - - // Graph the items. - document.body.appendChild(this.graph([ - 0x00FF0000, p1, "p1", p2, "p2", p3, "p3", p4, "p4", // points - 0xE0008800, p, "p", // plane - 0xE00000FF, s, "s" // sphere - ], {conformal: true, gl: true, grid: true})); -}); +// in the default view, e4 + e5 is the point at infinity +CGA3 = Algebra(4, 1); +v1 = CGA3.inline(() => 1e1 + 1e5)(); +v2 = CGA3.inline(() => 1e2 + 1e5)(); +v3 = CGA3.inline(() => 1e3 + 1e5)(); +w1 = CGA3.inline(() => 1e1 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(); +w2 = CGA3.inline(() => 1e2 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(); +w3 = CGA3.inline(() => 1e3 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(); +s = CGA3.inline(() => -Math.sqrt(1.2)*1e4 + Math.sqrt(0.2)*1e5); + +document.body.appendChild(CGA3.graph( + [ + 0xff00b0, v1, + 0x00ffb0, v2, + 0x00b0ff, v3, + 0x800040, w1, + 0x008040, w2, + 0x004080, w3, + 0xd0e0f0, s + ], + { + conformal: true, gl: true, grid: true + } +)); """ # === page construction === From 3b10c95d5ff92fb7f31475734c7a237f3d780780 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 25 Jun 2024 02:07:39 -0700 Subject: [PATCH 3/9] Clean up examples Declare JavaScript variables. Revise Julia comments to match new code. --- engine-proto/ganja-test/ganja-test.html | 16 ++++++++-------- engine-proto/ganja-test/ganja-test.jl | 24 ++++++++++-------------- 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/engine-proto/ganja-test/ganja-test.html b/engine-proto/ganja-test/ganja-test.html index 26eba9d..f1aeea7 100644 --- a/engine-proto/ganja-test/ganja-test.html +++ b/engine-proto/ganja-test/ganja-test.html @@ -19,14 +19,14 @@ +

diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl index 9ea621b..0808089 100644 --- a/engine-proto/ganja-test/ganja-test.jl +++ b/engine-proto/ganja-test/ganja-test.jl @@ -25,31 +25,51 @@ canvas { } """ +controls = """ +

+""" + graph_script = """ // in the default view, e4 + e5 is the point at infinity let CGA3 = Algebra(4, 1); -let v1 = CGA3.inline(() => 1e1 + 1e5)(); -let v2 = CGA3.inline(() => 1e2 + 1e5)(); -let v3 = CGA3.inline(() => 1e3 + 1e5)(); -let w1 = CGA3.inline(() => 1e1 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(); -let w2 = CGA3.inline(() => 1e2 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(); -let w3 = CGA3.inline(() => 1e3 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(); +let v = [ + CGA3.inline(() => 1e1 + 1e5)(), + CGA3.inline(() => 1e2 + 1e5)(), + CGA3.inline(() => 1e3 + 1e5)() +]; +let w = [ + CGA3.inline(() => 1e1 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(), + CGA3.inline(() => 1e2 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(), + CGA3.inline(() => 1e3 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)() +]; let s = CGA3.inline(() => -Math.sqrt(1.2)*1e4 + Math.sqrt(0.2)*1e5); -document.body.appendChild(CGA3.graph( - [ - 0xff00b0, v1, - 0x00ffb0, v2, - 0x00b0ff, v3, - 0x800040, w1, - 0x008040, w2, - 0x004080, w3, - 0xd0e0f0, s - ], +// create scene function +let scene = () => [ + 0xff00b0, v[0], + 0x00ffb0, v[1], + 0x00b0ff, v[2], + 0x800040, w[0], + 0x008040, w[1], + 0x004080, w[2], + 0xd0e0f0, s +]; + +// initialize graph +let gr = CGA3.graph( + scene, { conformal: true, gl: true, grid: true } -)); +) +document.body.appendChild(gr); + +// connect flip button +function flipPoint() { + v[0] = CGA3.Dual(CGA3.Mul(s, v[0])); + requestAnimationFrame(gr.update.bind(gr, scene)); +} +document.querySelector('#flip-button').addEventListener('click', flipPoint); """ # === page construction === @@ -65,5 +85,5 @@ style!(win, stylesheet) loadjs!(win, "https://unpkg.com/ganja.js") # launch Ganja visualization -body!(win, "", async=false) +body!(win, controls, async=false) js(win, JSString(graph_script)) From 06a9dda5bb58079db955675a8ef7a4ab9fed4945 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 25 Jun 2024 13:40:40 -0700 Subject: [PATCH 5/9] Play with reflections Try configuration of five tangent spheres. --- engine-proto/ganja-test/ganja-test.html | 36 +++++++++++++------------ engine-proto/ganja-test/ganja-test.jl | 36 +++++++++++++------------ 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/engine-proto/ganja-test/ganja-test.html b/engine-proto/ganja-test/ganja-test.html index e1da682..e0d59bb 100644 --- a/engine-proto/ganja-test/ganja-test.html +++ b/engine-proto/ganja-test/ganja-test.html @@ -17,31 +17,25 @@ -

+

diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl index 0808089..a5d7f6b 100644 --- a/engine-proto/ganja-test/ganja-test.jl +++ b/engine-proto/ganja-test/ganja-test.jl @@ -26,33 +26,27 @@ canvas { """ controls = """ -

+

""" graph_script = """ // in the default view, e4 + e5 is the point at infinity let CGA3 = Algebra(4, 1); let v = [ - CGA3.inline(() => 1e1 + 1e5)(), - CGA3.inline(() => 1e2 + 1e5)(), - CGA3.inline(() => 1e3 + 1e5)() + CGA3.inline(() => Math.sqrt(0.5)*( 1e1 + 1e2 + 1e3 + 1e5))(), + CGA3.inline(() => Math.sqrt(0.5)*( 1e1 - 1e2 - 1e3 + 1e5))(), + CGA3.inline(() => Math.sqrt(0.5)*(-1e1 + 1e2 - 1e3 + 1e5))(), + CGA3.inline(() => Math.sqrt(0.5)*(-1e1 - 1e2 + 1e3 + 1e5))(), + CGA3.inline(() => -Math.sqrt(3)*1e4 + Math.sqrt(2)*1e5)() ]; -let w = [ - CGA3.inline(() => 1e1 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(), - CGA3.inline(() => 1e2 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)(), - CGA3.inline(() => 1e3 - Math.sqrt(0.2)*1e4 + Math.sqrt(1.2)*1e5)() -]; -let s = CGA3.inline(() => -Math.sqrt(1.2)*1e4 + Math.sqrt(0.2)*1e5); // create scene function let scene = () => [ 0xff00b0, v[0], 0x00ffb0, v[1], 0x00b0ff, v[2], - 0x800040, w[0], - 0x008040, w[1], - 0x004080, w[2], - 0xd0e0f0, s + 0x8040ff, v[3], + 0xc0c0c0, v[4] ]; // initialize graph @@ -65,11 +59,19 @@ let gr = CGA3.graph( document.body.appendChild(gr); // connect flip button -function flipPoint() { - v[0] = CGA3.Dual(CGA3.Mul(s, v[0])); +function flip() { + for (let n = 0; n < 4; ++n) { + // reflect + v[n] = CGA3.Mul(CGA3.Mul(v[4], v[n]), v[4]); + + // de-noise + for (let k = 6; k < v[n].length; ++k) { + v[n][k] = 0; + } + } requestAnimationFrame(gr.update.bind(gr, scene)); } -document.querySelector('#flip-button').addEventListener('click', flipPoint); +document.querySelector('#flip-button').addEventListener('click', flip); """ # === page construction === From b7b5b9386b4cf9ca4f4f213bdc7f4066a868eadf Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 25 Jun 2024 16:30:19 -0700 Subject: [PATCH 6/9] Load elements from Julia into Ganja.js --- engine-proto/ganja-test/ganja-test.jl | 159 ++++++++++++++------------ 1 file changed, 89 insertions(+), 70 deletions(-) diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl index a5d7f6b..69b768f 100644 --- a/engine-proto/ganja-test/ganja-test.jl +++ b/engine-proto/ganja-test/ganja-test.jl @@ -1,17 +1,30 @@ using Blink -import Blink: JSString -# === styling utility === +# === utilities === -style!(w, stylesheet) = @js win begin - @var style = document.createElement("style"); - style.appendChild(document.createTextNode($stylesheet)); - document.head.appendChild(style); +append_to_head!(w, type, content) = @js win begin + @var element = document.createElement($type) + element.appendChild(document.createTextNode($content)) + document.head.appendChild(element) end -# === page source === +style!(w, stylesheet) = append_to_head!(w, "style", stylesheet) -stylesheet = """ +script!(w, code) = append_to_head!(w, "script", code) + +function add_element!(vec) + full_vec = [0; vec; fill(0, 26)] + @js win elements.push(@new CGA3($full_vec)) +end + +# === build page === + +# create window and open developer console +win = Window() +opentools(win) + +# set stylesheet +style!(win, """ body { background-color: #ffe0f0; } @@ -23,69 +36,75 @@ canvas { min-height: 600px; max-height: 600px; } -""" - -controls = """ -

-""" - -graph_script = """ -// in the default view, e4 + e5 is the point at infinity -let CGA3 = Algebra(4, 1); -let v = [ - CGA3.inline(() => Math.sqrt(0.5)*( 1e1 + 1e2 + 1e3 + 1e5))(), - CGA3.inline(() => Math.sqrt(0.5)*( 1e1 - 1e2 - 1e3 + 1e5))(), - CGA3.inline(() => Math.sqrt(0.5)*(-1e1 + 1e2 - 1e3 + 1e5))(), - CGA3.inline(() => Math.sqrt(0.5)*(-1e1 - 1e2 + 1e3 + 1e5))(), - CGA3.inline(() => -Math.sqrt(3)*1e4 + Math.sqrt(2)*1e5)() -]; - -// create scene function -let scene = () => [ - 0xff00b0, v[0], - 0x00ffb0, v[1], - 0x00b0ff, v[2], - 0x8040ff, v[3], - 0xc0c0c0, v[4] -]; - -// initialize graph -let gr = CGA3.graph( - scene, - { - conformal: true, gl: true, grid: true - } -) -document.body.appendChild(gr); - -// connect flip button -function flip() { - for (let n = 0; n < 4; ++n) { - // reflect - v[n] = CGA3.Mul(CGA3.Mul(v[4], v[n]), v[4]); - - // de-noise - for (let k = 6; k < v[n].length; ++k) { - v[n][k] = 0; - } - } - requestAnimationFrame(gr.update.bind(gr, scene)); -} -document.querySelector('#flip-button').addEventListener('click', flip); -""" - -# === page construction === - -# create window and open developer console -win = Window() -opentools(win) - -# set stylesheet -style!(win, stylesheet) +""") # load Ganja.js loadjs!(win, "https://unpkg.com/ganja.js") -# launch Ganja visualization -body!(win, controls, async=false) -js(win, JSString(graph_script)) +# create global functions and variables +script!(win, """ + // create algebra + var CGA3 = Algebra(4, 1); + + // in the default view, e4 + e5 is the point at infinity + var elements = []; + + // create scene function + let scene = () => [ + 0xff00b0, elements[0], + 0x00ffb0, elements[1], + 0x00b0ff, elements[2], + 0x8040ff, elements[3], + 0xc0c0c0, elements[4] + ]; + + // declare visualization handle + var graph; + + function flip() { + for (let n = 0; n < 4; ++n) { + // reflect + elements[n] = CGA3.Mul(CGA3.Mul(elements[4], elements[n]), elements[4]); + + // de-noise + for (let k = 6; k < elements[n].length; ++k) { + elements[n][k] = 0; + } + } + requestAnimationFrame(graph.update.bind(graph, scene)); + } +""") + +# set up controls +body!(win, """ +

+""", async=false) + +# === set up visualization === + +# list elements. in the default view, e4 + e5 is the point at infinity +elements = sqrt(0.5) * BigFloat[ + 1 1 -1 -1 0; + 1 -1 1 -1 0; + 1 -1 -1 1 0; + 0 0 0 0 -sqrt(6); + 1 1 1 1 2 +] + +# load elements +for vec in eachcol(elements) + add_element!(vec) +end + +# initialize visualization +@js win begin + graph = CGA3.graph( + scene, + Dict( + "conformal" => true, + "gl" => true, + "grid" => true + ) + ) + document.body.appendChild(graph); +end \ No newline at end of file From 182b5bb9f69f7e7bbbc524da85eb43fa62549510 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 25 Jun 2024 17:57:16 -0700 Subject: [PATCH 7/9] Generate palette automatically --- engine-proto/ganja-test/ganja-test.html | 44 ++++++++++++-------- engine-proto/ganja-test/ganja-test.jl | 53 ++++++++++++++++--------- 2 files changed, 63 insertions(+), 34 deletions(-) diff --git a/engine-proto/ganja-test/ganja-test.html b/engine-proto/ganja-test/ganja-test.html index e0d59bb..d6efc90 100644 --- a/engine-proto/ganja-test/ganja-test.html +++ b/engine-proto/ganja-test/ganja-test.html @@ -21,43 +21,55 @@ diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl index 69b768f..b944eae 100644 --- a/engine-proto/ganja-test/ganja-test.jl +++ b/engine-proto/ganja-test/ganja-test.jl @@ -1,4 +1,5 @@ using Blink +using Colors # === utilities === @@ -13,8 +14,22 @@ style!(w, stylesheet) = append_to_head!(w, "style", stylesheet) script!(w, code) = append_to_head!(w, "script", code) function add_element!(vec) + # add element full_vec = [0; vec; fill(0, 26)] - @js win elements.push(@new CGA3($full_vec)) + n = @js win elements.push(@new CGA3($full_vec)) + + # generate palette. this is Gadfly's `default_discrete_colors` palette, + # available under the MIT license + palette = distinguishable_colors( + n, + [LCHab(70, 60, 240)], + transform = c -> deuteranopic(c, 0.5), + lchoices = Float64[65, 70, 75, 80], + cchoices = Float64[0, 50, 60, 70], + hchoices = range(0, stop=330, length=24) + ) + palette_packed = [RGB24(c).color for c in palette] + @js win palette = $palette_packed end # === build page === @@ -45,26 +60,28 @@ loadjs!(win, "https://unpkg.com/ganja.js") script!(win, """ // create algebra var CGA3 = Algebra(4, 1); - - // in the default view, e4 + e5 is the point at infinity + + // initialize element list and palette var elements = []; - - // create scene function - let scene = () => [ - 0xff00b0, elements[0], - 0x00ffb0, elements[1], - 0x00b0ff, elements[2], - 0x8040ff, elements[3], - 0xc0c0c0, elements[4] - ]; - + var palette = []; + // declare visualization handle var graph; - + + // create scene function + function scene() { + commands = []; + for (let n = 0; n < elements.length; ++n) { + commands.push(palette[n], elements[n]); + } + return commands; + } + function flip() { - for (let n = 0; n < 4; ++n) { + let last = elements.length - 1; + for (let n = 0; n < last; ++n) { // reflect - elements[n] = CGA3.Mul(CGA3.Mul(elements[4], elements[n]), elements[4]); + elements[n] = CGA3.Mul(CGA3.Mul(elements[last], elements[n]), elements[last]); // de-noise for (let k = 6; k < elements[n].length; ++k) { @@ -78,7 +95,7 @@ script!(win, """ # set up controls body!(win, """

-""", async=false) +""", async = false) # === set up visualization === @@ -106,5 +123,5 @@ end "grid" => true ) ) - document.body.appendChild(graph); + document.body.appendChild(graph) end \ No newline at end of file From 665cb30ce0bf4bc442f5fcfbca24b51d73c1d116 Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Tue, 25 Jun 2024 23:31:00 -0700 Subject: [PATCH 8/9] Correct indentation of CSS --- engine-proto/ganja-test/ganja-test.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl index b944eae..19578bd 100644 --- a/engine-proto/ganja-test/ganja-test.jl +++ b/engine-proto/ganja-test/ganja-test.jl @@ -40,17 +40,17 @@ opentools(win) # set stylesheet style!(win, """ -body { - background-color: #ffe0f0; -} + body { + background-color: #ffe0f0; + } -/* needed to keep Ganja canvas from blowing up */ -canvas { - min-width: 600px; - max-width: 600px; - min-height: 600px; - max-height: 600px; -} + /* needed to keep Ganja canvas from blowing up */ + canvas { + min-width: 600px; + max-width: 600px; + min-height: 600px; + max-height: 600px; + } """) # load Ganja.js From a3b1f4920c24c401c240308582009f28580bc9fe Mon Sep 17 00:00:00 2001 From: Aaron Fenyes Date: Wed, 26 Jun 2024 00:41:21 -0700 Subject: [PATCH 9/9] Build construction viewer module --- engine-proto/ConstructionViewer.jl | 123 ++++++++++++++++++++++++++ engine-proto/ganja-test/ganja-test.jl | 2 +- 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 engine-proto/ConstructionViewer.jl diff --git a/engine-proto/ConstructionViewer.jl b/engine-proto/ConstructionViewer.jl new file mode 100644 index 0000000..efa7293 --- /dev/null +++ b/engine-proto/ConstructionViewer.jl @@ -0,0 +1,123 @@ +module Viewer + +using Blink +using Colors + +export ConstructionViewer, display! + +# === Blink utilities === + +append_to_head!(w, type, content) = @js w begin + @var element = document.createElement($type) + element.appendChild(document.createTextNode($content)) + document.head.appendChild(element) +end + +style!(w, stylesheet) = append_to_head!(w, "style", stylesheet) + +script!(w, code) = append_to_head!(w, "script", code) + +# === construction viewer === + +mutable struct ConstructionViewer + win::Window + + function ConstructionViewer() + # create window and open developer console + win = Window() + opentools(win) + + # set stylesheet + style!(win, """ + /* needed to keep Ganja canvas from blowing up */ + canvas { + min-width: 600px; + max-width: 600px; + min-height: 600px; + max-height: 600px; + } + """) + + # load Ganja.js + loadjs!(win, "https://unpkg.com/ganja.js") + + # create global functions and variables + script!(win, """ + // create algebra + var CGA3 = Algebra(4, 1); + + // initialize element list and palette + var elements = []; + var palette = []; + + // declare visualization handle + var graph; + + // create scene function + function scene() { + commands = []; + for (let n = 0; n < elements.length; ++n) { + commands.push(palette[n], elements[n]); + } + return commands; + } + """) + + # create view + @js win begin + graph = CGA3.graph( + scene, + Dict( + "conformal" => true, + "gl" => true, + "grid" => true + ) + ) + document.body.replaceChildren(graph) + end + + new(win) + end +end + +function display!(viewer::ConstructionViewer, elements::Matrix) + # load elements + elements_full = [ + [0; elt; fill(0, 26)] + for elt in eachcol(elements) + ] + @js viewer.win elements = $elements_full.map((elt) -> @new CGA3(elt)) + + # generate palette. this is Gadfly's `default_discrete_colors` palette, + # available under the MIT license + palette = distinguishable_colors( + length(elements_full), + [LCHab(70, 60, 240)], + transform = c -> deuteranopic(c, 0.5), + lchoices = Float64[65, 70, 75, 80], + cchoices = Float64[0, 50, 60, 70], + hchoices = range(0, stop=330, length=24) + ) + palette_packed = [RGB24(c).color for c in palette] + @js viewer.win palette = $palette_packed + + # update view + @js viewer.win requestAnimationFrame(graph.update.bind(graph, scene)); +end + +end + +# ~~~ sandbox setup ~~~ + +# in the default view, e4 + e5 is the point at infinity +elements = sqrt(0.5) * BigFloat[ + 1 1 -1 -1 0; + 1 -1 1 -1 0; + 1 -1 -1 1 0; + 0 0 0 0 -sqrt(6); + 1 1 1 1 2 +] + +# show construction +viewer = Viewer.ConstructionViewer() +Viewer.display!(viewer, elements) \ No newline at end of file diff --git a/engine-proto/ganja-test/ganja-test.jl b/engine-proto/ganja-test/ganja-test.jl index 19578bd..6c55061 100644 --- a/engine-proto/ganja-test/ganja-test.jl +++ b/engine-proto/ganja-test/ganja-test.jl @@ -3,7 +3,7 @@ using Colors # === utilities === -append_to_head!(w, type, content) = @js win begin +append_to_head!(w, type, content) = @js w begin @var element = document.createElement($type) element.appendChild(document.createTextNode($content)) document.head.appendChild(element)