演示地址: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)
}
}
}