diff --git a/lang-trials/rust-benchmark/.gitignore b/lang-trials/rust-benchmark/.gitignore
deleted file mode 100644
index 5b910ca..0000000
--- a/lang-trials/rust-benchmark/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-target/*
-dist/*
-Cargo.lock
\ No newline at end of file
diff --git a/lang-trials/rust-benchmark/Cargo.toml b/lang-trials/rust-benchmark/Cargo.toml
deleted file mode 100644
index 8dde7b0..0000000
--- a/lang-trials/rust-benchmark/Cargo.toml
+++ /dev/null
@@ -1,35 +0,0 @@
-[package]
-name = "sycamore-trial"
-version = "0.1.0"
-authors = ["Aaron"]
-edition = "2021"
-
-[features]
-default = ["console_error_panic_hook"]
-
-[dependencies]
-nalgebra = "0.33.0"
-sycamore = "0.9.0-beta.2"
-typenum = "1.17.0"
-
-# The `console_error_panic_hook` crate provides better debugging of panics by
-# logging them with `console.error`. This is great for development, but requires
-# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
-# code size when deploying.
-console_error_panic_hook = { version = "0.1.7", optional = true }
-
-[dependencies.web-sys]
-version = "0.3.69"
-features = [
- 'CanvasRenderingContext2d',
- 'HtmlCanvasElement',
- 'Window',
- 'Performance'
-]
-
-[dev-dependencies]
-wasm-bindgen-test = "0.3.34"
-
-[profile.release]
-opt-level = "s" # optimize for small code size
-debug = true # include debug symbols
diff --git a/lang-trials/rust-benchmark/index.html b/lang-trials/rust-benchmark/index.html
deleted file mode 100644
index 82823fc..0000000
--- a/lang-trials/rust-benchmark/index.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
- The circular law
-
-
-
-
diff --git a/lang-trials/rust-benchmark/main.css b/lang-trials/rust-benchmark/main.css
deleted file mode 100644
index f79e62c..0000000
--- a/lang-trials/rust-benchmark/main.css
+++ /dev/null
@@ -1,23 +0,0 @@
-body {
- margin-left: 20px;
- margin-top: 20px;
- color: #fcfcfc;
- background-color: #202020;
-}
-
-#app {
- display: flex;
- flex-direction: column;
- width: 600px;
-}
-
-canvas {
- float: left;
- background-color: #020202;
- border-radius: 10px;
- margin-top: 5px;
-}
-
-input {
- margin-top: 5px;
-}
\ No newline at end of file
diff --git a/lang-trials/rust-benchmark/notes b/lang-trials/rust-benchmark/notes
deleted file mode 100644
index 79a4030..0000000
--- a/lang-trials/rust-benchmark/notes
+++ /dev/null
@@ -1,13 +0,0 @@
-in profiling, most time is being spent in the `reflect` method:
-
-f64:
- sycamore_trial-3d0aca3efee8b5fd.wasm.nalgebra::geometry::reflection::Reflection::reflect::h7899977a4ba0b1d3
- sycamore_trial-3d0aca3efee8b5fd.wasm.nalgebra::geometry::reflection::Reflection::reflect::hc337c3cb6e3b4061
- sycamore_trial-3d0aca3efee8b5fd.wasm.nalgebra::geometry::reflection::Reflection::reflect_rows::h43d0f6838d0c2833
-
-f32:
- sycamore_trial-3d0aca3efee8b5fd.wasm.nalgebra::geometry::reflection::Reflection::reflect::h0e8ec322f198f847
- sycamore_trial-3d0aca3efee8b5fd.wasm.nalgebra::geometry::reflection::Reflection::reflect::h9928bdd5e72743ea
- sycamore_trial-3d0aca3efee8b5fd.wasm.nalgebra::geometry::reflection::Reflection::reflect_rows::h49f571fd8fc9b0f2
-
-in one test, we spent 4000 ms in "WASM closure", but the enveloping "VoidFunction" takes 1300 ms longer. in another test, though, there's no overhang; the 7000 ms we spent in `rand_eigval_series` accounts for basically the entire load time, and matches the clock timing
diff --git a/lang-trials/rust-benchmark/src/engine.rs b/lang-trials/rust-benchmark/src/engine.rs
deleted file mode 100644
index a2661aa..0000000
--- a/lang-trials/rust-benchmark/src/engine.rs
+++ /dev/null
@@ -1,164 +0,0 @@
-use nalgebra::{*, allocator::Allocator};
-use std::f64::consts::{PI, E};
-/*use std::ops::Sub;*/
-/*use typenum::{B1, UInt, UTerm};*/
-
-/* dynamic matrices */
-pub fn rand_eigval_series(time_res: usize) -> Vec, Dyn>>
- where
- N: ToTypenum + DimName + DimSub,
- DefaultAllocator:
- Allocator +
- Allocator +
- Allocator<>::Output> +
- Allocator>::Output>
-{
- // initialize the random matrix
- let dim = N::try_to_usize().unwrap();
- let mut rand_mat = DMatrix::::from_fn(dim, dim, |j, k| {
- let n = j*dim + k;
- E*((n*n) as f64) % 2.0 - 1.0
- }) * (3.0 / (dim as f64)).sqrt();
-
- // initialize the rotation step
- let mut rot_step = DMatrix::::identity(dim, dim);
- let max_freq = 4;
- for n in (0..dim).step_by(2) {
- let ang = PI * ((n % max_freq) as f64) / (time_res as f64);
- let ang_cos = ang.cos();
- let ang_sin = ang.sin();
- rot_step[(n, n)] = ang_cos;
- rot_step[(n+1, n)] = ang_sin;
- rot_step[(n, n+1)] = -ang_sin;
- rot_step[(n+1, n+1)] = ang_cos;
- }
-
- // find the eigenvalues
- let mut eigval_series = Vec::, Dyn>>::with_capacity(time_res);
- eigval_series.push(rand_mat.complex_eigenvalues());
- for _ in 1..time_res {
- rand_mat = &rot_step * rand_mat;
- eigval_series.push(rand_mat.complex_eigenvalues());
- }
- eigval_series
-}
-
-/* dynamic single float matrices */
-/*pub fn rand_eigval_series(time_res: usize) -> Vec, Dyn>>
- where
- N: ToTypenum + DimName + DimSub,
- DefaultAllocator:
- Allocator +
- Allocator +
- Allocator<>::Output> +
- Allocator>::Output>
-{
- // initialize the random matrix
- let dim = N::try_to_usize().unwrap();
- let mut rand_mat = DMatrix::::from_fn(dim, dim, |j, k| {
- let n = j*dim + k;
- (E as f32)*((n*n) as f32) % 2.0_f32 - 1.0_f32
- }) * (3.0_f32 / (dim as f32)).sqrt();
-
- // initialize the rotation step
- let mut rot_step = DMatrix::::identity(dim, dim);
- let max_freq = 4;
- for n in (0..dim).step_by(2) {
- let ang = (PI as f32) * ((n % max_freq) as f32) / (time_res as f32);
- let ang_cos = ang.cos();
- let ang_sin = ang.sin();
- rot_step[(n, n)] = ang_cos;
- rot_step[(n+1, n)] = ang_sin;
- rot_step[(n, n+1)] = -ang_sin;
- rot_step[(n+1, n+1)] = ang_cos;
- }
-
- // find the eigenvalues
- let mut eigval_series = Vec::, Dyn>>::with_capacity(time_res);
- eigval_series.push(rand_mat.complex_eigenvalues());
- for _ in 1..time_res {
- rand_mat = &rot_step * rand_mat;
- eigval_series.push(rand_mat.complex_eigenvalues());
- }
- eigval_series
-}*/
-
-/* static matrices. should only be used when the dimension is really small */
-/*pub fn rand_eigval_series(time_res: usize) -> Vec, N>>
- where
- N: ToTypenum + DimName + DimSub,
- DefaultAllocator:
- Allocator +
- Allocator +
- Allocator<>::Output> +
- Allocator>::Output>
-{
- // initialize the random matrix
- let dim = N::try_to_usize().unwrap();
- let mut rand_mat = OMatrix::::from_fn(|j, k| {
- let n = j*dim + k;
- E*((n*n) as f64) % 2.0 - 1.0
- }) * (3.0 / (dim as f64)).sqrt();
- /*let mut rand_mat = OMatrix::::identity();*/
-
- // initialize the rotation step
- let mut rot_step = OMatrix::::identity();
- let max_freq = 4;
- for n in (0..dim).step_by(2) {
- let ang = PI * ((n % max_freq) as f64) / (time_res as f64);
- let ang_cos = ang.cos();
- let ang_sin = ang.sin();
- rot_step[(n, n)] = ang_cos;
- rot_step[(n+1, n)] = ang_sin;
- rot_step[(n, n+1)] = -ang_sin;
- rot_step[(n+1, n+1)] = ang_cos;
- }
-
- // find the eigenvalues
- let mut eigval_series = Vec::, N>>::with_capacity(time_res);
- eigval_series.push(rand_mat.complex_eigenvalues());
- for _ in 1..time_res {
- rand_mat = &rot_step * rand_mat;
- eigval_series.push(rand_mat.complex_eigenvalues());
- }
- eigval_series
-}*/
-
-/* another attempt at static matrices. i couldn't get the types to work out */
-/*pub fn random_eigval_series(time_res: usize) -> Vec, Const>>
- where
- Const: ToTypenum,
- as ToTypenum>::Typenum: Sub>,
- < as ToTypenum>::Typenum as Sub>>::Output: ToConst
-{
- // initialize the random matrix
- /*let mut rand_mat = SMatrix::::zeros();
- for n in 0..N*N {
- rand_mat[n] = E*((n*n) as f64) % 2.0 - 1.0;
- }*/
- let rand_mat = OMatrix::, Const>::from_fn(|j, k| {
- let n = j*N + k;
- E*((n*n) as f64) % 2.0 - 1.0
- });
-
- // initialize the rotation step
- let mut rot_step = OMatrix::, Const>::identity();
- let max_freq = 4;
- for n in (0..N).step_by(2) {
- let ang = PI * ((n % max_freq) as f64) / (time_res as f64);
- let ang_cos = ang.cos();
- let ang_sin = ang.sin();
- rot_step[(n, n)] = ang_cos;
- rot_step[(n+1, n)] = ang_sin;
- rot_step[(n, n+1)] = -ang_sin;
- rot_step[(n+1, n+1)] = ang_cos;
- }
-
- // find the eigenvalues
- let mut eigvals = Vec::, Const>>::with_capacity(time_res);
- unsafe { eigvals.set_len(time_res); }
- for t in 0..time_res {
- eigvals[t] = rand_mat.complex_eigenvalues();
- }
- eigvals
-}*/
\ No newline at end of file
diff --git a/lang-trials/rust-benchmark/src/main.rs b/lang-trials/rust-benchmark/src/main.rs
deleted file mode 100644
index 9662dd7..0000000
--- a/lang-trials/rust-benchmark/src/main.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-use nalgebra::*;
-use std::f64::consts::PI as PI;
-use sycamore::{prelude::*, rt::{JsCast, JsValue}};
-use web_sys::window;
-
-mod engine;
-
-fn main() {
- // set up a config option that forwards panic messages to `console.error`
- #[cfg(feature = "console_error_panic_hook")]
- console_error_panic_hook::set_once();
-
- sycamore::render(|| {
- let time_res: usize = 100;
- let time_step = create_signal(0.0);
- let run_time_report = create_signal(-1.0);
- let display = create_node_ref();
-
- on_mount(move || {
- let performance = window().unwrap().performance().unwrap();
- let start_time = performance.now();
- let eigval_series = engine::rand_eigval_series::(time_res);
- let run_time = performance.now() - start_time;
- run_time_report.set(run_time);
-
- let canvas = display
- .get::()
- .unchecked_into::();
- let ctx = canvas
- .get_context("2d")
- .unwrap()
- .unwrap()
- .dyn_into::()
- .unwrap();
- ctx.set_fill_style(&JsValue::from("white"));
-
- create_effect(move || {
- // center and normalize the coordinate system
- let width = canvas.width() as f64;
- let height = canvas.height() as f64;
- ctx.set_transform(1.0, 0.0, 0.0, -1.0, 0.5*width, 0.5*height).unwrap();
-
- // clear the previous frame
- ctx.clear_rect(-0.5*width, -0.5*width, width, height);
-
- // find the resolution
- const R_DISP: f64 = 1.5;
- let res = width / (2.0*R_DISP);
-
- // draw the eigenvalues
- let eigvals = &eigval_series[time_step.get() as usize];
- for n in 0..eigvals.len() {
- ctx.begin_path();
- ctx.arc(
- /* typecast only needed for single float version */
- res * f64::from(eigvals[n].re),
- res * f64::from(eigvals[n].im),
- 3.0,
- 0.0, 2.0*PI
- ).unwrap();
- ctx.fill();
- }
- });
- });
-
- view! {
- div(id="app") {
- div { (run_time_report.get()) " ms" }
- canvas(ref=display, width="600", height="600")
- input(
- type="range",
- max=(time_res - 1).to_string(),
- bind:valueAsNumber=time_step
- )
- }
- }
- });
-}
\ No newline at end of file
diff --git a/lang-trials/rust/.gitignore b/lang-trials/rust/.gitignore
index 5b910ca..1d4e644 100644
--- a/lang-trials/rust/.gitignore
+++ b/lang-trials/rust/.gitignore
@@ -1,3 +1,2 @@
target/*
-dist/*
-Cargo.lock
\ No newline at end of file
+dist/*
\ No newline at end of file
diff --git a/lang-trials/scala-benchmark/.gitignore b/lang-trials/scala-benchmark/.gitignore
deleted file mode 100644
index 9f2a453..0000000
--- a/lang-trials/scala-benchmark/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-target
-sbt.json
\ No newline at end of file
diff --git a/lang-trials/scala-benchmark/build.sbt b/lang-trials/scala-benchmark/build.sbt
deleted file mode 100644
index 507885d..0000000
--- a/lang-trials/scala-benchmark/build.sbt
+++ /dev/null
@@ -1,9 +0,0 @@
-enablePlugins(ScalaJSPlugin)
-
-name := "Circular Law"
-scalaVersion := "3.4.2"
-scalaJSUseMainModuleInitializer := true
-
-libraryDependencies += "com.raquo" %%% "laminar" % "17.0.0"
-libraryDependencies += "ai.dragonfly" %%% "slash" % "0.3.1"
-libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.8.0"
diff --git a/lang-trials/scala-benchmark/index.html b/lang-trials/scala-benchmark/index.html
deleted file mode 100644
index f9eb11c..0000000
--- a/lang-trials/scala-benchmark/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- The circular law
-
-
-
-
-
diff --git a/lang-trials/scala-benchmark/main.css b/lang-trials/scala-benchmark/main.css
deleted file mode 100644
index f79e62c..0000000
--- a/lang-trials/scala-benchmark/main.css
+++ /dev/null
@@ -1,23 +0,0 @@
-body {
- margin-left: 20px;
- margin-top: 20px;
- color: #fcfcfc;
- background-color: #202020;
-}
-
-#app {
- display: flex;
- flex-direction: column;
- width: 600px;
-}
-
-canvas {
- float: left;
- background-color: #020202;
- border-radius: 10px;
- margin-top: 5px;
-}
-
-input {
- margin-top: 5px;
-}
\ No newline at end of file
diff --git a/lang-trials/scala-benchmark/project/build.properties b/lang-trials/scala-benchmark/project/build.properties
deleted file mode 100644
index ee4c672..0000000
--- a/lang-trials/scala-benchmark/project/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-sbt.version=1.10.1
diff --git a/lang-trials/scala-benchmark/project/plugins.sbt b/lang-trials/scala-benchmark/project/plugins.sbt
deleted file mode 100644
index e5b2699..0000000
--- a/lang-trials/scala-benchmark/project/plugins.sbt
+++ /dev/null
@@ -1 +0,0 @@
-addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
diff --git a/lang-trials/scala-benchmark/src/main/scala/CircularLawApp.scala b/lang-trials/scala-benchmark/src/main/scala/CircularLawApp.scala
deleted file mode 100644
index 950e661..0000000
--- a/lang-trials/scala-benchmark/src/main/scala/CircularLawApp.scala
+++ /dev/null
@@ -1,89 +0,0 @@
-import com.raquo.laminar.api.L.{*, given}
-import narr.*
-import org.scalajs.dom
-import org.scalajs.dom.document
-import scala.math.{cos, sin}
-import slash.matrix.Matrix
-import slash.matrix.decomposition.Eigen
-
-object CircularLawApp:
- val canvas = canvasTag(widthAttr := 600, heightAttr := 600)
- val ctx = canvas.ref.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]
-
- val (eigvalSeries, runTimeReport) = randEigvalSeries[60]()
- val timeStepState = Var("0")
-
- def draw(timeStep: String): Unit =
- // center and normalize the coordinate system
- val width = canvas.ref.width
- val height = canvas.ref.height
- ctx.setTransform(1d, 0d, 0d, -1d, 0.5*width, 0.5*height)
-
- // clear the previous frame
- ctx.clearRect(-0.5*width, -0.5*width, width, height)
-
- // find the resolution
- val rDisp: Double = 1.5
- val res = width / (2*rDisp)
-
- // draw the eigenvalues
- val eigvals = eigvalSeries(timeStep.toInt)
- for n <- 0 to eigvals(0).length-1 do
- ctx.beginPath()
- ctx.arc(
- res * eigvals(0)(n),
- res * eigvals(1)(n),
- 3d,
- 0d, 2*math.Pi
- )
- ctx.fill()
-
- def eigvalsRotated[N <: Int](A: Matrix[N, N], time: Double)(using ValueOf[N]): (NArray[Double], NArray[Double]) =
- // create transformation
- val maxFreq = 4
- val T = Matrix.identity[N, N]
- val dim: Int = valueOf[N]
- for n <- 0 to dim by 2 do
- val a = cos(math.Pi * time * (n % maxFreq))
- val b = sin(math.Pi * time * (n % maxFreq))
- T(n, n) = a
- T(n+1, n) = b
- T(n, n+1) = -b
- T(n+1, n+1) = a
-
- // find eigenvalues
- val eigen = Eigen(T*A)
- (
- eigen.realEigenvalues.asInstanceOf[NArray[Double]],
- eigen.imaginaryEigenvalues.asInstanceOf[NArray[Double]]
- )
-
- def randEigvalSeries[N <: Int]()(using ValueOf[N]): (List[(NArray[Double], NArray[Double])], String) =
- val timeRes = 100
- val dim: Int = valueOf[N]
- val startTime = System.currentTimeMillis()
- val A = new Matrix[N, N](
- NArray.tabulate(dim*dim)(k => (math.E*k*k) % 2 - 1)
- ).times(math.sqrt(3d / dim))
- val series = List.tabulate(timeRes)(t => eigvalsRotated(A, t.toDouble / timeRes))
- val runTime = System.currentTimeMillis() - startTime
- (series, runTime.toString() + " ms")
-
- def main(args: Array[String]): Unit =
- ctx.fillStyle = "white"
-
- lazy val app = div(
- idAttr := "app",
- div(runTimeReport),
- canvas,
- input(
- typ := "range",
- maxAttr := (eigvalSeries.length-1).toString,
- controlled(
- value <-- timeStepState.signal,
- onInput.mapToValue --> timeStepState.writer
- ),
- timeStepState.signal --> draw
- )
- )
- renderOnDomContentLoaded(document.body, app)
diff --git a/lang-trials/scala/.gitignore b/lang-trials/scala/.gitignore
deleted file mode 100644
index 9f2a453..0000000
--- a/lang-trials/scala/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-target
-sbt.json
\ No newline at end of file
diff --git a/lang-trials/scala/build.sbt b/lang-trials/scala/build.sbt
deleted file mode 100644
index 908e7e9..0000000
--- a/lang-trials/scala/build.sbt
+++ /dev/null
@@ -1,12 +0,0 @@
-enablePlugins(ScalaJSPlugin)
-
-name := "Lattice Circle"
-scalaVersion := "3.4.2"
-
-// This is an application with a main method
-scalaJSUseMainModuleInitializer := true
-
-libraryDependencies += "com.raquo" %%% "laminar" % "17.0.0"
-/*libraryDependencies += "org.scalanlp" %% "breeze" % "2.1.0"*/
-libraryDependencies += "ai.dragonfly" %%% "slash" % "0.3.1"
-libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "2.8.0"
diff --git a/lang-trials/scala/index.html b/lang-trials/scala/index.html
deleted file mode 100644
index ff30e9f..0000000
--- a/lang-trials/scala/index.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- Lattice circle
-
-
-
-
-
diff --git a/lang-trials/scala/main.css b/lang-trials/scala/main.css
deleted file mode 100644
index 3aedb99..0000000
--- a/lang-trials/scala/main.css
+++ /dev/null
@@ -1,45 +0,0 @@
-body {
- margin-left: 20px;
- margin-top: 20px;
- color: #fcfcfc;
- background-color: #202020;
-}
-
-input {
- color: inherit;
- background-color: #020202;
- border: 1px solid #606060;
- min-width: 40px;
- border-radius: 4px;
-}
-
-input.point-1 {
- border-color: #ba5d09;
-}
-
-input.point-2 {
- border-color: #0e8a06;
-}
-
-input.point-3 {
- border-color: #8951fb;
-}
-
-#data-panel {
- float: left;
- margin-left: 20px;
- display: grid;
- grid-template-columns: auto auto;
- gap: 10px 10px;
- width: 120px;
-}
-
-#data-panel > div {
- text-align: center;
-}
-
-canvas {
- float: left;
- background-color: #020202;
- border-radius: 10px;
-}
diff --git a/lang-trials/scala/project/build.properties b/lang-trials/scala/project/build.properties
deleted file mode 100644
index ee4c672..0000000
--- a/lang-trials/scala/project/build.properties
+++ /dev/null
@@ -1 +0,0 @@
-sbt.version=1.10.1
diff --git a/lang-trials/scala/project/plugins.sbt b/lang-trials/scala/project/plugins.sbt
deleted file mode 100644
index e5b2699..0000000
--- a/lang-trials/scala/project/plugins.sbt
+++ /dev/null
@@ -1 +0,0 @@
-addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
diff --git a/lang-trials/scala/src/main/scala/LatticeCircleApp.scala b/lang-trials/scala/src/main/scala/LatticeCircleApp.scala
deleted file mode 100644
index 12ee36c..0000000
--- a/lang-trials/scala/src/main/scala/LatticeCircleApp.scala
+++ /dev/null
@@ -1,160 +0,0 @@
-// based on the Laminar example app
-//
-// https://github.com/raquo/laminar-examples/blob/master/src/main/scala/App.scala
-//
-// and Li Haoyi's example canvas app
-//
-// http://www.lihaoyi.com/hands-on-scala-js/#MakingaCanvasApp
-//
-
-import com.raquo.laminar.api.L.{*, given}
-import narr.*
-import org.scalajs.dom
-import org.scalajs.dom.document
-import scala.math
-import slash.matrix.*
-
-class Circle(var centerX: Double, var centerY: Double, var radius: Double)
-
-object LatticeCircleApp:
- val canvas = canvasTag(widthAttr := 600, heightAttr := 600)
- val ctx = canvas.ref.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]
- val data = List("-1", "0", "0", "-1", "1", "0").map(Var(_))
-
- def circThru(points: Matrix[3, 2]): Option[Circle] =
- // build the matrix that maps the circle's coefficient vector to the
- // negative of the linear part of the circle's equation, evaluated at the
- // given points
- val negLinPart = Matrix.ones[3, 3]
- negLinPart.setMatrix(0, 0, points * 2.0)
-
- // find the quadrdatic part of the circle's equation, evaluated at the given
- // points
- val quadPart = Matrix[3, 1](
- NArray.tabulate[Double](3)(
- k => points(k, 0)*points(k, 0) + points(k, 1)*points(k, 1)
- )
- )
-
- // find the circle's coefficient vector, and from there its center and
- // radius
- try
- val coeffs = negLinPart.solve(quadPart)
- val centerX = coeffs(0, 0)
- val centerY = coeffs(1, 0)
- Some(Circle(
- centerX,
- centerY,
- math.sqrt(coeffs(2, 0) + centerX*centerX + centerY*centerY)
- ))
- catch
- _ => return None
-
- def draw(): Unit =
- // center and normalize the coordinate system
- val width = canvas.ref.width
- val height = canvas.ref.height
- ctx.setTransform(1.0, 0.0, 0.0, -1.0, 0.5*width, 0.5*height)
-
- // clear the previous frame
- ctx.clearRect(-0.5*width, -0.5*width, width, height)
-
- // find the resolution
- val rDisp = 5.0
- val res = width / (2.0*rDisp)
-
- // set colors
- val highlightStyle = "white"
- val gridStyle = "#404040"
- val pointFillStyles = List("#ba5d09", "#0e8a06", "#8951fb")
- val pointStrokeStyles = List("#f89142", "#58c145", "#c396fc")
-
- // draw the grid
- val rGrid = (rDisp - 0.01).floor.toInt
- val edgeScr = res * rDisp
- ctx.strokeStyle = gridStyle
- for t <- -rGrid to rGrid do
- val tScr = res * t
-
- // draw horizontal grid line
- ctx.beginPath();
- ctx.moveTo(-edgeScr, tScr)
- ctx.lineTo(edgeScr, tScr)
- ctx.stroke()
-
- // draw vertical grid line
- ctx.beginPath();
- ctx.moveTo(tScr, -edgeScr)
- ctx.lineTo(tScr, edgeScr)
- ctx.stroke()
-
- // find and draw the circle through the given points
- val dataNow = NArray.tabulate(6)(n =>
- try
- data(n).signal.now().toDouble
- catch
- _ => Double.NaN
- )
- if dataNow.forall(t => t == t.floor) then
- // all of the coordinates are integer and non-NaN
- val points = Matrix[3, 2](dataNow)
- circThru(points) match
- case Some(circ) =>
- ctx.beginPath()
- ctx.strokeStyle = highlightStyle
- ctx.arc(
- res * circ.centerX,
- res * circ.centerY,
- res * circ.radius,
- 0.0, 2.0*math.Pi
- )
- ctx.stroke()
- case None =>
-
- // draw the data points
- for n <- 0 to 2 do
- val indX = 2*n
- val indY = indX + 1
- if
- dataNow(indX) == dataNow(indX).floor &&
- dataNow(indY) == dataNow(indY).floor
- then
- ctx.beginPath()
- ctx.fillStyle = pointFillStyles(n)
- ctx.strokeStyle = pointStrokeStyles(n)
- ctx.arc(
- res * dataNow(indX),
- res * dataNow(indY),
- 3.0,
- 0.0, 2.0*math.Pi
- )
- ctx.fill()
- ctx.stroke()
-
- def coordInput(n: Int): Input =
- input(
- typ := "number",
- cls := s"point-${(1.0 + 0.5*n).floor.toInt}",
- controlled(
- value <-- data(n).signal,
- onInput.mapToValue --> data(n).writer
- ),
- data(n).signal --> { _ => draw() }
- )
-
- def main(args: Array[String]): Unit =
- lazy val app = div(
- canvas,
- div(
- idAttr := "data-panel",
- div("x"),
- div("y"),
- coordInput(0),
- coordInput(1),
- coordInput(2),
- coordInput(3),
- coordInput(4),
- coordInput(5)
- )
- )
- renderOnDomContentLoaded(document.body, app)