Skip to content

Instantly share code, notes, and snippets.

@gzoritchak
Created July 5, 2017 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gzoritchak/bae900c3e4dd5b116ef4a855d979f3da to your computer and use it in GitHub Desktop.
Save gzoritchak/bae900c3e4dd5b116ef4a855d979f3da to your computer and use it in GitHub Desktop.
Just a test of JavaFx animation.
package io.data2viz.svg
import javafx.animation.AnimationTimer
import javafx.application.Application
import javafx.scene.Group
import javafx.scene.Scene
import javafx.scene.paint.Color
import javafx.scene.shape.Circle
import javafx.scene.shape.Rectangle
import javafx.stage.Stage
fun main(args: Array<String>) {
Application.launch(Main::class.java)
}
class Main : Application() {
override fun start(stage: Stage) {
stage.title = "JavaFX Scene Graph Demo"
val domainToSvg = scale.linear.pointsToPoints(
Point() linkedTo Point(400.0, 400.0),
Point(5.0, 5.0) linkedTo Point(x = 800.0)
)
stage.scene = svg {
val circlesAndParticules = (1..2000).map {
val circleElement = circle{}
val particle = RandomParticule()
Pair(circleElement, particle)
}
val animation = object :AnimationTimer() {
override fun handle(now: Long) {
circlesAndParticules.forEach {
it.second.updatePositionAndSpeed()
val localPoint = domainToSvg(it.second.position)
it.first.circle.translateX = localPoint.x
it.first.circle.translateY = localPoint.y
}
}
}
animation.start()
}
stage.show()
}
private fun svg(init: SVGElement.() -> Unit): Scene {
val root = Group()
val svg = SVGElement(root)
init(svg)
return Scene(root, 800.0, 800.0, Color.WHITE)
}
}
/**
* A particule with a 2D position that will move randomly beetween approximatively -5,-5 and +5,+5
*/
class RandomParticule {
var position = Point()
var speed = Speed()
fun updatePositionAndSpeed() {
position += speed
speed += Speed(
.04 * (Math.random() - .5) - .05 * speed.vx - .0005 * position.x.toDouble(),
.04 * (Math.random() - .5) - .05 * speed.vy - .0005 * position.y.toDouble()
)
}
}
data class Point(val x:Double = 0.0, val y:Double = 0.0) {
operator fun plus(speed: Speed) = Point(x + speed.vx, y + speed.vy)
operator fun plus(other: Point) = Point(x + other.x, y + other.y)
operator fun div(value:Number) = Point(x/value.toDouble(), y/value.toDouble())
}
data class Speed(val vx: Double = 0.0, val vy: Double = 0.0) {
operator fun plus(speed: Speed) = Speed(vx + speed.vx, vy + speed.vy)
}
class SVGElement(val root: Group) {
fun rect(init: RectElement.() -> Unit) {
val rect = RectElement()
init(rect)
root.children.add(rect.rectangle)
}
fun circle(init: CircleElement.() -> Unit = {}): CircleElement {
val circleElement = CircleElement()
init(circleElement)
root.children.add(circleElement.circle)
return circleElement
}
}
class CircleElement(val circle: Circle = Circle()) {
init {
circle.radius = 5.0
}
}
class RectElement(val rectangle: Rectangle = Rectangle()) {
var width: Double
get() = rectangle.width
set(value) {
rectangle.width = value
}
var height: Double
get() = rectangle.height
set(value) {
rectangle.height = value
}
}
class scale {
object linear {
fun pointsToPoints(start: DomainToViz<Point, Point>, end: DomainToViz<Point, Point>) =
{ pt: Point ->
Point(
numberToNumber(start.domain.x linkedTo start.viz.x, end.domain.x linkedTo end.viz.x)(pt.x),
numberToNumber(start.domain.y linkedTo start.viz.y, end.domain.y linkedTo end.viz.y)(pt.y))
}
fun numberToNumber(start: DomainToViz<Double, Double>, end: DomainToViz<Double, Double>): (Double) -> Double =
{ domain: Double ->
interpolateNumber(start.viz, end.viz).invoke(
uninterpolate(start.domain as Number, end.domain).invoke(domain).toDouble()) as Double
}
}
}
data class DomainToViz<out A, out B>(
val domain: A,
val viz: B
)
fun interpolateNumber(a: Number, b: Number): (Number) -> Number = { t -> a.toDouble() + t.toDouble() * (b.toDouble() - a.toDouble()) }
fun uninterpolate(start: Number, end: Number): (Number) -> Number = { t -> (t.toDouble() - start.toDouble()) / (end.toDouble() - start.toDouble()) }
infix fun <A, B> A.linkedTo(that: B): DomainToViz<A, B> = DomainToViz(this, that)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment