package com.example.acapendulum20.canvas
|
|
|
|
import android.content.Context
|
|
import android.graphics.Canvas
|
|
import android.graphics.Color
|
|
import android.graphics.Paint
|
|
import android.util.AttributeSet
|
|
import android.view.View
|
|
import kotlinx.coroutines.delay
|
|
import kotlin.math.*
|
|
|
|
|
|
class CanvasPendulum @JvmOverloads constructor(
|
|
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
|
) : View(context, attrs, defStyleAttr) {
|
|
|
|
private val paint: Paint = Paint()
|
|
private lateinit var canvas: Canvas
|
|
private val mPendulum: Pendulum = Pendulum()
|
|
|
|
override fun onDraw(canvas: Canvas?) {
|
|
super.onDraw(canvas)
|
|
|
|
//if canvas not NULL then this canvas = it
|
|
canvas?.let {
|
|
this.canvas = it
|
|
}
|
|
|
|
//println("ONDRAW")
|
|
//draw line
|
|
mPendulum.startPosition.x = (width / 2).toFloat()
|
|
paint.isAntiAlias = true
|
|
paint.style = Paint.Style.STROKE
|
|
paint.color = Color.RED
|
|
paint.strokeWidth = 10f
|
|
this.canvas.drawLine(
|
|
mPendulum.startPosition.x,
|
|
mPendulum.startPosition.y,
|
|
mPendulum.stopPosition.x,
|
|
mPendulum.stopPosition.y,
|
|
paint
|
|
)
|
|
|
|
//draw circle
|
|
paint.style = Paint.Style.FILL_AND_STROKE
|
|
paint.strokeWidth = 1f
|
|
paint.color = Color.GRAY
|
|
canvas?.drawCircle(
|
|
mPendulum.stopPosition.x,
|
|
mPendulum.stopPosition.y,
|
|
mPendulum.ballr,
|
|
paint
|
|
)
|
|
|
|
//draw sensor left
|
|
paint.style = Paint.Style.FILL_AND_STROKE
|
|
paint.strokeWidth = 1f
|
|
paint.color = Color.RED
|
|
if (mPendulum.angleVelocity > 0) {
|
|
if (mPendulum.stopPosition.x < (width / 3) - 30f && mPendulum.stopPosition.x + 30 > (width / 3) - 30f - mPendulum.ballr) {
|
|
paint.style = Paint.Style.FILL_AND_STROKE
|
|
paint.strokeWidth = 10f
|
|
paint.color = Color.GREEN
|
|
}
|
|
}
|
|
canvas?.drawCircle((width / 3).toFloat(), 910f, 30f, paint)
|
|
|
|
//draw sensor right
|
|
paint.style = Paint.Style.FILL_AND_STROKE
|
|
paint.strokeWidth = 1f
|
|
paint.color = Color.RED
|
|
if (mPendulum.angleVelocity < 0) {
|
|
if (mPendulum.stopPosition.x > (width / 1.5) - 30f && mPendulum.stopPosition.x + 30 < (width / 1.5) + 30f + mPendulum.ballr) {
|
|
paint.style = Paint.Style.FILL_AND_STROKE
|
|
paint.strokeWidth = 10f
|
|
paint.color = Color.GREEN
|
|
}
|
|
}
|
|
canvas?.drawCircle((width / 1.5).toFloat(), 910f, 30f, paint)
|
|
|
|
startPendulum()
|
|
invalidate()
|
|
}
|
|
|
|
fun startPendulum() {
|
|
|
|
if (mPendulum.magneticField) {
|
|
|
|
var gravity = 0.981f
|
|
var damping = 0.996f
|
|
|
|
if (mPendulum.stopPosition.x > canvas.width / 4f && mPendulum.stopPosition.x <= canvas.width * 0.75f) {
|
|
gravity = 1.981f
|
|
|
|
if (mPendulum.stopPosition.x > canvas.width / 3.toFloat() && mPendulum.stopPosition.x <= canvas.width / 1.5.toFloat()) {
|
|
gravity = 2.981f
|
|
|
|
if (mPendulum.stopPosition.x >= canvas.width / 2.toFloat() - 3 && mPendulum.stopPosition.x <= canvas.width / 2.toFloat() + 3) {
|
|
damping = 0.3f
|
|
}
|
|
}
|
|
}
|
|
|
|
mPendulum.angleAcceleration =
|
|
((-1 * gravity / mPendulum.r) * (mPendulum.angle)).toFloat()
|
|
mPendulum.angleVelocity += mPendulum.angleAcceleration
|
|
mPendulum.angleVelocity *= damping
|
|
mPendulum.angle += mPendulum.angleVelocity
|
|
//Polar to cartesian conversion
|
|
mPendulum.stopPosition.x = mPendulum.r * (sin(mPendulum.angle)).toFloat()
|
|
mPendulum.stopPosition.y = mPendulum.r * (cos(mPendulum.angle)).toFloat()
|
|
//Origin transition
|
|
mPendulum.stopPosition.x += mPendulum.startPosition.x
|
|
}
|
|
|
|
if (!mPendulum.magneticField) {
|
|
val gravity = 0.981f
|
|
val damping = 0.996f
|
|
|
|
mPendulum.angleAcceleration =
|
|
((-1 * gravity / mPendulum.r) * (mPendulum.angle)).toFloat()
|
|
mPendulum.angleVelocity += mPendulum.angleAcceleration
|
|
mPendulum.angleVelocity *= damping
|
|
mPendulum.angle += mPendulum.angleVelocity
|
|
//Polar to cartesian conversion
|
|
mPendulum.stopPosition.x = mPendulum.r * (sin(mPendulum.angle)).toFloat()
|
|
mPendulum.stopPosition.y = mPendulum.r * (cos(mPendulum.angle)).toFloat()
|
|
//Origin transition
|
|
mPendulum.stopPosition.x += mPendulum.startPosition.x
|
|
}
|
|
}
|
|
|
|
fun startMagnet(magnet: Boolean) {
|
|
mPendulum.magneticField = magnet
|
|
}
|
|
|
|
fun stopMagnet(magnet: Boolean) {
|
|
mPendulum.magneticField = magnet
|
|
}
|
|
|
|
fun getVelocity(): Double {
|
|
var currentVelocity = mPendulum.angleVelocity * 1000
|
|
|
|
val roundoff = (currentVelocity * 100.0).roundToInt() / 100.0
|
|
return abs(roundoff)
|
|
}
|
|
}
|
|
|
|
class Position(var x: Float, var y: Float) {
|
|
|
|
}
|
|
|
|
class Pendulum {
|
|
|
|
var startPosition: Position = Position(0f, 0f)
|
|
var stopPosition: Position = Position(0f, 0f)
|
|
var r = 800f
|
|
|
|
//PI/6 Max ausschwingen
|
|
var angle: Double = Math.PI / 12
|
|
var angleVelocity: Float = 0.0f //
|
|
var angleAcceleration: Float = 0.0f //
|
|
var ballr: Float = 70.0f //
|
|
var magneticField: Boolean = false
|
|
}
|