From 1799a9a9096b945d9354000234a517e9b41790fb Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 3 Jun 2024 18:34:08 +0300 Subject: [PATCH] Fix ball on springs demo --- .../controls/constructor/models/MaterialPoint.kt | 10 ++++++++-- .../kscience/controls/constructor/units/coordinates.kt | 8 ++++++++ demo/constructor/src/jvmMain/kotlin/BodyOnSprings.kt | 6 ++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/MaterialPoint.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/MaterialPoint.kt index c03841c..cc44a85 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/MaterialPoint.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/models/MaterialPoint.kt @@ -26,17 +26,23 @@ public class MaterialPoint( private var currentForce = force.value private val movement = onTimer( + DefaultTimer.REALTIME, reads = setOf(velocity, position), writes = setOf(velocity, position) ) { prev, next -> val dtSeconds = (next - prev).toDouble(DurationUnit.SECONDS) // compute new value based on velocity and acceleration from the previous step - position.value += (velocity.value * dtSeconds).cast(Meters) + + val deltaR = (velocity.value * dtSeconds).cast(Meters) + (currentForce / mass.value * dtSeconds.pow(2) / 2).cast(Meters) + position.value += deltaR // compute new velocity based on acceleration on the previous step - velocity.value += (currentForce / mass.value * dtSeconds).cast(MetersPerSecond) + val deltaV = (currentForce / mass.value * dtSeconds).cast(MetersPerSecond) + //TODO apply energy correction + //val work = deltaR.length.value * currentForce.length.value + velocity.value += deltaV + currentForce = force.value } } \ No newline at end of file diff --git a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/units/coordinates.kt b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/units/coordinates.kt index 88d7bd6..027dbbb 100644 --- a/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/units/coordinates.kt +++ b/controls-constructor/src/commonMain/kotlin/space/kscience/controls/constructor/units/coordinates.kt @@ -1,5 +1,8 @@ package space.kscience.controls.constructor.units +import kotlin.math.pow +import kotlin.math.sqrt + public data class XY(val x: NumericalValue, val y: NumericalValue) public fun XY(x: Number, y: Number): XY = XY(NumericalValue(x), NumericalValue((y))) @@ -18,6 +21,11 @@ public data class XYZ( val z: NumericalValue, ) +public val XYZ.length: NumericalValue + get() = NumericalValue( + sqrt(x.value.pow(2) + y.value.pow(2) + z.value.pow(2)) + ) + public fun XYZ(x: Number, y: Number, z: Number): XYZ = XYZ(NumericalValue(x), NumericalValue((y)), NumericalValue(z)) diff --git a/demo/constructor/src/jvmMain/kotlin/BodyOnSprings.kt b/demo/constructor/src/jvmMain/kotlin/BodyOnSprings.kt index e937d1b..57bc426 100644 --- a/demo/constructor/src/jvmMain/kotlin/BodyOnSprings.kt +++ b/demo/constructor/src/jvmMain/kotlin/BodyOnSprings.kt @@ -16,8 +16,6 @@ import space.kscience.controls.constructor.models.MaterialPoint import space.kscience.controls.constructor.units.* import space.kscience.dataforge.context.Context import java.awt.Dimension -import kotlin.math.pow -import kotlin.math.sqrt private class Spring( @@ -33,7 +31,7 @@ private class Spring( */ val tension: DeviceState> = combineState(begin, end) { begin: XYZ, end: XYZ -> val delta = end - begin - val l = sqrt(delta.x.value.pow(2) + delta.y.value.pow(2) + delta.z.value.pow(2)) + val l = delta.length.value ((delta / l) * k * (l - l0.value)).cast(Newtons) } } @@ -87,7 +85,7 @@ private class BodyOnSprings( } fun main() = application { - val initialState = XYZ(0.01, 0.1, 0) + val initialState = XYZ(0, 0.4, 0) Window(title = "Ball on springs", onCloseRequest = ::exitApplication) { window.minimumSize = Dimension(400, 400)