using Blink using Colors # === 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) function add_element!(vec) # add element full_vec = [0; vec; fill(0, 26)] 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 === # create window and open developer console win = Window() opentools(win) # set stylesheet style!(win, """ 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; } """) # 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; } function flip() { let last = elements.length - 1; for (let n = 0; n < last; ++n) { // reflect elements[n] = CGA3.Mul(CGA3.Mul(elements[last], elements[n]), elements[last]); // 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