Scala trial: clean up Laminar interface
Also, drop unused Breeze code in favor of Slash.
This commit is contained in:
parent
4f30f31686
commit
0bd025dd14
@ -8,7 +8,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import com.raquo.laminar.api.L.{*, given}
|
import com.raquo.laminar.api.L.{*, given}
|
||||||
/*import breeze.linalg._*/
|
|
||||||
import narr.*
|
import narr.*
|
||||||
import org.scalajs.dom
|
import org.scalajs.dom
|
||||||
import org.scalajs.dom.document
|
import org.scalajs.dom.document
|
||||||
@ -20,57 +19,7 @@ class Circle(var centerX: Double, var centerY: Double, var radius: Double)
|
|||||||
object LatticeCircleApp:
|
object LatticeCircleApp:
|
||||||
val canvas = canvasTag(widthAttr := 600, heightAttr := 600)
|
val canvas = canvasTag(widthAttr := 600, heightAttr := 600)
|
||||||
val ctx = canvas.ref.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]
|
val ctx = canvas.ref.getContext("2d").asInstanceOf[dom.CanvasRenderingContext2D]
|
||||||
val dataBusList = List.tabulate(6)(_ => new EventBus[Double])
|
val data = List("-1", "0", "0", "-1", "1", "0").map(Var(_))
|
||||||
val dataStream = dataBusList(0).events
|
|
||||||
.combineWith(dataBusList(1).events)
|
|
||||||
.combineWith(dataBusList(2).events)
|
|
||||||
.combineWith(dataBusList(3).events)
|
|
||||||
.combineWith(dataBusList(4).events)
|
|
||||||
.combineWith(dataBusList(5).events)
|
|
||||||
.map(dataTuple => NArray(dataTuple(0), dataTuple(1), dataTuple(2), dataTuple(3), dataTuple(4), dataTuple(5)))
|
|
||||||
.filter(data => data.forall(!_.isNaN()))
|
|
||||||
/*
|
|
||||||
val dataList = List(-1.0, 0.0, 0.0, -1.0, 1.0, 0.0).map(Var(_))
|
|
||||||
val dataStream = dataList(0).signal
|
|
||||||
.combineWith(dataList(1).signal)
|
|
||||||
.combineWith(dataList(2).signal)
|
|
||||||
.combineWith(dataList(3).signal)
|
|
||||||
.combineWith(dataList(4).signal)
|
|
||||||
.combineWith(dataList(5).signal)
|
|
||||||
.map(dataTuple => NArray(dataTuple(0), dataTuple(1), dataTuple(2), dataTuple(3), dataTuple(4), dataTuple(5)))
|
|
||||||
*/
|
|
||||||
val pointStream = dataStream.map(data => Matrix[3, 2](data))
|
|
||||||
/* Breeze version */
|
|
||||||
/*
|
|
||||||
val pointStream = dataStream.map(data => new DenseMatrix(2, 3, Array(data(0), data(1), data(2), data(3), data(4), data(5))))
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Breeze version */
|
|
||||||
/*
|
|
||||||
def circThru(points: DenseMatrix[Double]): 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 = DenseMatrix.horzcat(
|
|
||||||
2.0*points.t,
|
|
||||||
DenseMatrix.ones[Double](3, 1)
|
|
||||||
)
|
|
||||||
|
|
||||||
// find the quadrdatic part of the circle's equation, evaluated at the given
|
|
||||||
// points
|
|
||||||
val quadPart = points(::, *).map(v => v dot v)
|
|
||||||
|
|
||||||
// find the circle's coefficient vector, and from there its center and
|
|
||||||
// radius
|
|
||||||
val coeffs = negLinPart \ quadPart
|
|
||||||
val centerX = coeffs(0, 0)
|
|
||||||
val centerY = coeffs(1, 0)
|
|
||||||
Circle(
|
|
||||||
centerX,
|
|
||||||
centerY,
|
|
||||||
math.sqrt(coeffs(2, 0) + centerX*centerX + centerY*centerY)
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
|
|
||||||
def circThru(points: Matrix[3, 2]): Option[Circle] =
|
def circThru(points: Matrix[3, 2]): Option[Circle] =
|
||||||
// build the matrix that maps the circle's coefficient vector to the
|
// build the matrix that maps the circle's coefficient vector to the
|
||||||
@ -78,8 +27,6 @@ object LatticeCircleApp:
|
|||||||
// given points
|
// given points
|
||||||
val negLinPart = Matrix.ones[3, 3]
|
val negLinPart = Matrix.ones[3, 3]
|
||||||
negLinPart.setMatrix(0, 0, points * 2.0)
|
negLinPart.setMatrix(0, 0, points * 2.0)
|
||||||
println("built neg lin part")
|
|
||||||
println(negLinPart)
|
|
||||||
|
|
||||||
// find the quadrdatic part of the circle's equation, evaluated at the given
|
// find the quadrdatic part of the circle's equation, evaluated at the given
|
||||||
// points
|
// points
|
||||||
@ -88,8 +35,6 @@ object LatticeCircleApp:
|
|||||||
k => points(k, 0)*points(k, 0) + points(k, 1)*points(k, 1)
|
k => points(k, 0)*points(k, 0) + points(k, 1)*points(k, 1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
println("build quad part")
|
|
||||||
println(quadPart)
|
|
||||||
|
|
||||||
// find the circle's coefficient vector, and from there its center and
|
// find the circle's coefficient vector, and from there its center and
|
||||||
// radius
|
// radius
|
||||||
@ -105,7 +50,7 @@ object LatticeCircleApp:
|
|||||||
catch
|
catch
|
||||||
_ => return None
|
_ => return None
|
||||||
|
|
||||||
def draw(points: Matrix[3, 2]): Unit =
|
def draw(): Unit =
|
||||||
// center and normalize the coordinate system
|
// center and normalize the coordinate system
|
||||||
val width = canvas.ref.width
|
val width = canvas.ref.width
|
||||||
val height = canvas.ref.height
|
val height = canvas.ref.height
|
||||||
@ -144,6 +89,15 @@ object LatticeCircleApp:
|
|||||||
ctx.stroke()
|
ctx.stroke()
|
||||||
|
|
||||||
// find and draw the circle through the given points
|
// 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
|
circThru(points) match
|
||||||
case Some(circ) =>
|
case Some(circ) =>
|
||||||
ctx.beginPath()
|
ctx.beginPath()
|
||||||
@ -159,95 +113,48 @@ object LatticeCircleApp:
|
|||||||
|
|
||||||
// draw the data points
|
// draw the data points
|
||||||
for n <- 0 to 2 do
|
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.beginPath()
|
||||||
ctx.fillStyle = pointFillStyles(n)
|
ctx.fillStyle = pointFillStyles(n)
|
||||||
ctx.strokeStyle = pointStrokeStyles(n)
|
ctx.strokeStyle = pointStrokeStyles(n)
|
||||||
ctx.arc(
|
ctx.arc(
|
||||||
res * points(n, 0),
|
res * dataNow(indX),
|
||||||
res * points(n, 1),
|
res * dataNow(indY),
|
||||||
3.0,
|
3.0,
|
||||||
0.0, 2.0*math.Pi
|
0.0, 2.0*math.Pi
|
||||||
)
|
)
|
||||||
ctx.fill()
|
ctx.fill()
|
||||||
ctx.stroke()
|
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 =
|
def main(args: Array[String]): Unit =
|
||||||
lazy val app = div(
|
lazy val app = div(
|
||||||
canvas,
|
canvas,
|
||||||
div(
|
div(
|
||||||
pointStream --> draw,
|
|
||||||
idAttr := "data-panel",
|
idAttr := "data-panel",
|
||||||
div("x"),
|
div("x"),
|
||||||
div("y"),
|
div("y"),
|
||||||
input(typ := "number", cls := "point-1", inContext(thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataBusList(0))),
|
coordInput(0),
|
||||||
input(typ := "number", cls := "point-1", inContext(thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataBusList(1))),
|
coordInput(1),
|
||||||
input(typ := "number", cls := "point-2", inContext(thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataBusList(2))),
|
coordInput(2),
|
||||||
input(typ := "number", cls := "point-2", inContext(thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataBusList(3))),
|
coordInput(3),
|
||||||
input(typ := "number", cls := "point-3", inContext(thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataBusList(4))),
|
coordInput(4),
|
||||||
input(typ := "number", cls := "point-3", inContext(thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataBusList(5)))
|
coordInput(5)
|
||||||
/* attempt to use controlled inputs */
|
|
||||||
/*
|
|
||||||
input(
|
|
||||||
typ := "number",
|
|
||||||
cls := "point-1",
|
|
||||||
controlled(
|
|
||||||
value <-- dataList(0).signal,
|
|
||||||
inContext(
|
|
||||||
thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataList(0).writer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
input(
|
|
||||||
typ := "number",
|
|
||||||
cls := "point-1",
|
|
||||||
controlled(
|
|
||||||
value <-- dataList(1).signal,
|
|
||||||
inContext(
|
|
||||||
thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataList(1).writer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
input(
|
|
||||||
typ := "number",
|
|
||||||
cls := "point-2",
|
|
||||||
controlled(
|
|
||||||
value <-- dataList(2).signal,
|
|
||||||
inContext(
|
|
||||||
thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataList(2).writer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
input(
|
|
||||||
typ := "number",
|
|
||||||
cls := "point-2",
|
|
||||||
controlled(
|
|
||||||
value <-- dataList(3).signal,
|
|
||||||
inContext(
|
|
||||||
thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataList(3).writer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
input(
|
|
||||||
typ := "number",
|
|
||||||
cls := "point-3",
|
|
||||||
controlled(
|
|
||||||
value <-- dataList(4).signal,
|
|
||||||
inContext(
|
|
||||||
thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataList(4).writer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
input(
|
|
||||||
typ := "number",
|
|
||||||
cls := "point-3",
|
|
||||||
controlled(
|
|
||||||
value <-- dataList(5).signal,
|
|
||||||
inContext(
|
|
||||||
thisNode => onInput.mapTo(thisNode.ref.valueAsNumber) --> dataList(5).writer
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
*/
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
renderOnDomContentLoaded(document.body, app)
|
renderOnDomContentLoaded(document.body, app)
|
||||||
|
Loading…
Reference in New Issue
Block a user