tornadofx使用circle、AnimationTimer、timeline動畫演示蒙特卡洛演算法求PI值
阿新 • • 發佈:2019-08-26
演示地址:https://www.bilibili.com/video/av59421525
import javafx.animation.AnimationTimer import javafx.scene.paint.Color import javafx.scene.shape.Circle import javafx.util.Duration import tornadofx.* class 蒙特卡洛演算法 : App(蒙特卡洛演算法求Pi::class) class 蒙特卡洛演算法求Pi : View("learn 蒙特卡洛演算法") { // 動畫計時器 val aniTimer = AniTimer(this) val result = stringProperty() val numPoint = intProperty() val Msg = stringProperty() val numPointInCircle = intProperty() lateinit var circle0: Circle override val root = borderpane { top = vbox(5) { label(result) { isWrapText = true } label(Msg) hbox(5) { button("run").action { // ani() aniTimer.start() } button("stop").action { // ani() aniTimer.stop() } } } center = group { rectangle(0, 0, 600, 600) { fill = Color.YELLOW } circle0 = circle(300, 300, 300) { fill = Color.AZURE } prefHeight = 800.0 prefWidth = 800.0 } } fun paint() { timeline { keyframe(Duration.seconds(0.0010)) { // 用迴圈包裹,可以調節繪製速度 (0..100).forEach { val p = point((0..600).random().toDouble(), (0..600).random().toDouble()) val c = Circle(p.x, p.y, 1.0) // 判斷圓circle0是否包含點p,方法1 // val b = ((p.x - circle0.centerX).pow(2).plus((p.y - circle0.centerY).pow(2)) <= circle0.radius.pow(2)) // if (b) { // c.fill = Color.RED // } // 判斷圓circle0是否包含點p,方法2 if (circle0.contains(p)) { c.fill = Color.RED numPointInCircle.value++ } root.center.add(c) numPoint.value++ val piEstimate = 4.0 * numPointInCircle.value/ numPoint.value Msg.value = "總點數:${numPoint.value} -- 圓內點數:${numPointInCircle.value} -- Pi估計值: ${piEstimate} " } } } } // 此方法可以停止動畫 class AniTimer(val learnV: 蒙特卡洛演算法求Pi) : AnimationTimer() { var lastTime = 0L override fun handle(now: Long) { if ((now - lastTime) > 10000000) { lastTime = now } else { return } learnV.paint() } } }
控制檯輸出版本:
import javafx.scene.paint.Color
import javafx.scene.shape.Circle
import tornadofx.*
fun main(){
// 矩形邊長
val recWidth=1000
val r=recWidth/2.toDouble()
val circle0 = Circle(r, r.toDouble(), r)
// 總點數
val numPoint = intProperty()
// 圓內點數
val numPointInCircle = intProperty()
val Msg = stringProperty()
// 1000萬個點
val n=10000000
(0..n).forEach {
val p = point((0..recWidth).random().toDouble(), (0..recWidth).random().toDouble())
val c = Circle(p.x, p.y, 1.0)
// 判斷圓circle0是否包含點p,方法1
// val b = ((p.x - circle0.centerX).pow(2).plus((p.y - circle0.centerY).pow(2)) <= circle0.radius.pow(2))
// if (b) {
// c.fill = Color.RED
// }
// 判斷圓circle0是否包含點p,方法2
if (circle0.contains(p)) {
c.fill = Color.RED
numPointInCircle.value++
}
numPoint.value++
val piEstimate = 4.0 * numPointInCircle.value/ numPoint.value
// 每隔1萬個點輸出一次
if(numPoint.value/10000==1){
Msg.value = "總點數:${numPoint.value} -- 圓內點數:${numPointInCircle.value} -- Pi估計值: ${piEstimate} "
println(Msg.value)
}
}
}