This commit is contained in:
Alexander Nozik 2019-12-31 16:06:38 +03:00
parent dac794b8ca
commit d36542ac5b
17 changed files with 196 additions and 122 deletions

View File

@ -1,10 +1,7 @@
package hep.dataforge.vis.common package hep.dataforge.vis.common
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.names.Name import hep.dataforge.names.*
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty
import kotlinx.serialization.Transient import kotlinx.serialization.Transient
@ -75,7 +72,7 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
protected abstract fun createGroup(name: Name): MutableVisualGroup protected abstract fun createGroup(name: Name): MutableVisualGroup
/** /**
* Add named or unnamed child to the group. If key is [null] the child is considered unnamed. Both key and value are not * Add named or unnamed child to the group. If key is null the child is considered unnamed. Both key and value are not
* allowed to be null in the same time. If name is present and [child] is null, the appropriate element is removed. * allowed to be null in the same time. If name is present and [child] is null, the appropriate element is removed.
*/ */
override fun set(name: Name, child: VisualObject?) { override fun set(name: Name, child: VisualObject?) {
@ -102,9 +99,13 @@ abstract class AbstractVisualGroup : AbstractVisualObject(), MutableVisualGroup
structureChangeListeners.forEach { it.callback(name, child) } structureChangeListeners.forEach { it.callback(name, child) }
} }
operator fun set(key: String, child: VisualObject?) = if (key.isBlank()) { operator fun set(key: String, child: VisualObject?): Unit {
child?.let { addStatic(child) } if (key.isBlank()) {
if(child!= null) {
addStatic(child)
}
} else { } else {
set(key.asName(), child) set(key.toName(), child)
}
} }
} }

View File

@ -92,7 +92,8 @@ class ThreeCanvas(val three: ThreePlugin, val spec: CanvasSpec) : Renderer<Visua
override fun render(obj: VisualObject3D, meta: Meta) { override fun render(obj: VisualObject3D, meta: Meta) {
content = obj content = obj
scene.add(three.buildObject3D(obj)) val object3D = three.buildObject3D(obj)
scene.add(object3D)
} }
} }

View File

@ -26,7 +26,6 @@ object ThreeLabelFactory : ThreeFactory<Label3D> {
val context = canvas.getContext("2d") as CanvasRenderingContext2D val context = canvas.getContext("2d") as CanvasRenderingContext2D
context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}" context.font = "Bold ${obj.fontSize}pt ${obj.fontFamily}"
context.fillStyle = obj.color ?: "black" context.fillStyle = obj.color ?: "black"
//context.textAlign = CanvasTextAlign.CENTER
context.textBaseline = CanvasTextBaseline.MIDDLE context.textBaseline = CanvasTextBaseline.MIDDLE
val metrics = context.measureText(obj.text) val metrics = context.measureText(obj.text)
//canvas.width = metrics.width.toInt() //canvas.width = metrics.width.toInt()

View File

@ -2,9 +2,11 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.meta.node import hep.dataforge.meta.node
import hep.dataforge.vis.spatial.PolyLine import hep.dataforge.vis.spatial.PolyLine
import hep.dataforge.vis.spatial.layer import hep.dataforge.vis.spatial.color
import hep.dataforge.vis.spatial.three.ThreeMaterials.DEFAULT_LINE_COLOR
import info.laht.threekt.core.Geometry import info.laht.threekt.core.Geometry
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
import info.laht.threekt.math.Color
import info.laht.threekt.objects.LineSegments import info.laht.threekt.objects.LineSegments
import kotlin.reflect.KClass import kotlin.reflect.KClass
@ -18,11 +20,13 @@ object ThreeLineFactory : ThreeFactory<PolyLine> {
val material = val material =
ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node) ThreeMaterials.getLineMaterial(obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node)
material.linewidth = obj.thickness.toDouble()
material.color = obj.color?.let { Color(it) }?: DEFAULT_LINE_COLOR
return LineSegments(geometry, material).apply { return LineSegments(geometry, material).apply {
updatePosition(obj) updatePosition(obj)
layers.enable(obj.layer) //layers.enable(obj.layer)
//add listener to object properties //add listener to object properties
obj.onPropertyChange(this) { propertyName, _, _ -> obj.onPropertyChange(this) { propertyName, _, _ ->
updateProperty(obj, propertyName) updateProperty(obj, propertyName)

View File

@ -6,7 +6,6 @@ import hep.dataforge.vis.common.Colors
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.Material3D import hep.dataforge.vis.spatial.Material3D
import info.laht.threekt.materials.LineBasicMaterial import info.laht.threekt.materials.LineBasicMaterial
import info.laht.threekt.materials.Material
import info.laht.threekt.materials.MeshBasicMaterial import info.laht.threekt.materials.MeshBasicMaterial
import info.laht.threekt.materials.MeshPhongMaterial import info.laht.threekt.materials.MeshPhongMaterial
import info.laht.threekt.math.Color import info.laht.threekt.math.Color
@ -25,7 +24,7 @@ object ThreeMaterials {
// private val materialCache = HashMap<Meta, Material>() // private val materialCache = HashMap<Meta, Material>()
private val lineMaterialCache = HashMap<Meta?, Material>() private val lineMaterialCache = HashMap<Meta?, LineBasicMaterial>()
// fun buildMaterial(meta: Meta): Material = // fun buildMaterial(meta: Meta): Material =
@ -37,11 +36,11 @@ object ThreeMaterials {
// //side = 2 // //side = 2
// } // }
fun getLineMaterial(meta: Meta?): Material = lineMaterialCache.getOrPut(meta) { fun getLineMaterial(meta: Meta?): LineBasicMaterial = lineMaterialCache.getOrPut(meta) {
LineBasicMaterial().apply { LineBasicMaterial().apply {
color = meta["color"]?.color() ?: DEFAULT_LINE_COLOR color = meta[Material3D.COLOR_KEY]?.color() ?: DEFAULT_LINE_COLOR
opacity = meta["opacity"].double ?: 1.0 opacity = meta[Material3D.OPACITY_KEY].double ?: 1.0
transparent = meta["transparent"].boolean ?: (opacity < 1.0) transparent = opacity < 1.0
linewidth = meta["thickness"].double ?: 1.0 linewidth = meta["thickness"].double ?: 1.0
} }
} }
@ -98,7 +97,7 @@ fun Mesh.updateMaterial(obj: VisualObject) {
color = meta[Material3D.COLOR_KEY]?.color() ?: ThreeMaterials.DEFAULT_COLOR color = meta[Material3D.COLOR_KEY]?.color() ?: ThreeMaterials.DEFAULT_COLOR
specular = meta[Material3D.SPECULAR_COLOR]!!.color() specular = meta[Material3D.SPECULAR_COLOR]!!.color()
opacity = meta[Material3D.OPACITY_KEY]?.double ?: 1.0 opacity = meta[Material3D.OPACITY_KEY]?.double ?: 1.0
transparent = opacity <= 0.0 transparent = opacity < 1.0
wireframe = meta[Material3D.WIREFRAME_KEY].boolean ?: false wireframe = meta[Material3D.WIREFRAME_KEY].boolean ?: false
needsUpdate = true needsUpdate = true
} }
@ -106,7 +105,7 @@ fun Mesh.updateMaterial(obj: VisualObject) {
MeshBasicMaterial().apply { MeshBasicMaterial().apply {
color = meta[Material3D.COLOR_KEY]?.color() ?: ThreeMaterials.DEFAULT_COLOR color = meta[Material3D.COLOR_KEY]?.color() ?: ThreeMaterials.DEFAULT_COLOR
opacity = meta[Material3D.OPACITY_KEY]?.double ?: 1.0 opacity = meta[Material3D.OPACITY_KEY]?.double ?: 1.0
transparent = opacity <= 0.0 transparent = opacity < 1.0
wireframe = meta[Material3D.WIREFRAME_KEY].boolean ?: false wireframe = meta[Material3D.WIREFRAME_KEY].boolean ?: false
needsUpdate = true needsUpdate = true
} }

View File

@ -2,10 +2,7 @@ package hep.dataforge.vis.spatial.three
import hep.dataforge.context.* import hep.dataforge.context.*
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.names.Name import hep.dataforge.names.*
import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty
import hep.dataforge.names.startsWith
import hep.dataforge.vis.common.VisualObject import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
@ -43,14 +40,13 @@ class ThreePlugin : AbstractPlugin() {
is Proxy -> proxyFactory(obj) is Proxy -> proxyFactory(obj)
is VisualGroup3D -> { is VisualGroup3D -> {
val group = ThreeGroup() val group = ThreeGroup()
obj.children.forEach { (name, child) -> obj.children.forEach { (token, child) ->
if (child is VisualObject3D && child.ignore != true) { if (child is VisualObject3D && child.ignore != true) {
try { try {
val object3D = buildObject3D(child) val object3D = buildObject3D(child)
object3D.name = name.toString() group[token] = object3D
group.add(object3D)
} catch (ex: Throwable) { } catch (ex: Throwable) {
logger.error(ex) { "Failed to render $name" } logger.error(ex) { "Failed to render $child" }
} }
} }
} }
@ -71,6 +67,31 @@ class ThreePlugin : AbstractPlugin() {
visible = obj.visible ?: true visible = obj.visible ?: true
} }
} }
obj.onChildrenChange(this) { name, child ->
if (name.isEmpty()) {
logger.error { "Children change with empty namr on $group" }
return@onChildrenChange
}
val parentName = name.cutLast()
val childName = name.last()!!
//removing old object
findChild(name)?.let { oldChild ->
oldChild.parent?.remove(oldChild)
}
//adding new object
if (child != null && child is VisualObject3D) {
try {
val object3D = buildObject3D(child)
set(name, object3D)
} catch (ex: Throwable) {
logger.error(ex) { "Failed to render $child" }
}
}
}
} }
} }
is Composite -> compositeFactory(obj) is Composite -> compositeFactory(obj)
@ -93,7 +114,34 @@ class ThreePlugin : AbstractPlugin() {
} }
} }
fun Object3D.findChild(name: Name): Object3D? { internal operator fun Object3D.set(token: NameToken, object3D: Object3D) {
object3D.name = token.toString()
add(object3D)
}
internal fun Object3D.getOrCreateGroup(name: Name): Object3D {
return when {
name.isEmpty() -> this
name.length == 1 -> {
val token = name.first()!!
children.find { it.name == token.toString() } ?: info.laht.threekt.objects.Group().also { group ->
group.name = token.toString()
this.add(group)
}
}
else -> getOrCreateGroup(name.first()!!.asName()).getOrCreateGroup(name.cutFirst())
}
}
internal operator fun Object3D.set(name: Name, obj: Object3D) {
when (name.length) {
0 -> error("Can't set object with an empty name")
1 -> set(name.first()!!, obj)
else -> getOrCreateGroup(name.cutLast())[name.last()!!] = obj
}
}
internal fun Object3D.findChild(name: Name): Object3D? {
return when { return when {
name.isEmpty() -> this name.isEmpty() -> this
name.length == 1 -> this.children.find { it.name == name.first()!!.toString() } name.length == 1 -> this.children.find { it.name == name.first()!!.toString() }

View File

@ -5,7 +5,10 @@ import hep.dataforge.meta.float
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.meta.node import hep.dataforge.meta.node
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import info.laht.threekt.core.* import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.DirectGeometry
import info.laht.threekt.core.Face3
import info.laht.threekt.core.Geometry
import info.laht.threekt.external.controls.OrbitControls import info.laht.threekt.external.controls.OrbitControls
import info.laht.threekt.materials.Material import info.laht.threekt.materials.Material
import info.laht.threekt.math.Euler import info.laht.threekt.math.Euler
@ -14,16 +17,6 @@ import info.laht.threekt.objects.Mesh
import info.laht.threekt.textures.Texture import info.laht.threekt.textures.Texture
import kotlin.math.PI import kotlin.math.PI
/**
* Utility methods for three.kt.
* TODO move to three project
*/
@Suppress("FunctionName")
fun Group(children: Collection<Object3D>) = info.laht.threekt.objects.Group().apply {
children.forEach { this.add(it) }
}
val VisualObject3D.euler get() = Euler(rotationX, rotationY, rotationZ, rotationOrder.name) val VisualObject3D.euler get() = Euler(rotationX, rotationY, rotationZ, rotationOrder.name)
val MetaItem<*>.vector get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f) val MetaItem<*>.vector get() = Vector3(node["x"].float ?: 0f, node["y"].float ?: 0f, node["z"].float ?: 0f)

View File

@ -1,9 +1,8 @@
import org.openjfx.gradle.JavaFXOptions
import scientifik.useSerialization import scientifik.useSerialization
plugins { plugins {
id("scientifik.mpp") id("scientifik.mpp")
id("org.openjfx.javafxplugin") //id("org.openjfx.javafxplugin")
id("application") id("application")
} }
@ -50,6 +49,14 @@ kotlin {
implementation("io.ktor:ktor-serialization:$ktor_version") implementation("io.ktor:ktor-serialization:$ktor_version")
} }
} }
jsMain{
dependencies{
implementation("io.ktor:ktor-client-js:$ktor_version")
implementation("io.ktor:ktor-client-serialization-js:$ktor_version")
implementation(npm("text-encoding"))
implementation(npm("abort-controller"))
}
}
} }
} }
@ -57,6 +64,6 @@ application {
mainClassName = "ru.mipt.npm.muon.monitor.server/MMServerKt" mainClassName = "ru.mipt.npm.muon.monitor.server/MMServerKt"
} }
configure<JavaFXOptions> { //configure<JavaFXOptions> {
modules("javafx.controls") // modules("javafx.controls")
} //}

View File

@ -12,9 +12,9 @@ typealias Track = List<Point3D>
* *
*/ */
@Serializable @Serializable
data class Event(val track: Track?, val hits: Collection<String>) { data class Event(val id: Int, val track: Track?, val hits: Collection<String>) {
/** // /**
* The unique identity for given set of hits. One identity could correspond to different tracks // * The unique identity for given set of hits. One identity could correspond to different tracks
*/ // */
val id get() = hits.sorted().joinToString(separator = ", ", prefix = "[", postfix = "]"); // val id get() = hits.sorted().joinToString(separator = ", ", prefix = "[", postfix = "]")
} }

View File

@ -60,7 +60,7 @@ class Model {
map[pixel]?.color("blue") map[pixel]?.color("blue")
} }
private fun reset() { fun reset() {
map.values.forEach { map.values.forEach {
it.setProperty(Material3D.MATERIAL_COLOR_KEY, null) it.setProperty(Material3D.MATERIAL_COLOR_KEY, null)
} }
@ -73,7 +73,9 @@ class Model {
highlight(it) highlight(it)
} }
event.track?.let { event.track?.let {
tracks.polyline(*it.toTypedArray()) tracks.polyline(*it.toTypedArray(), name = "track[${event.id}]"){
thickness = 4
}
} }
} }

View File

@ -125,8 +125,8 @@ object Monitor {
const val PIXEL_XY_SPACING = 123.2 const val PIXEL_XY_SPACING = 123.2
const val PIXEL_Z_SIZE = 30.0 const val PIXEL_Z_SIZE = 30.0
const val CENTRAL_LAYER_Z = 0.0 const val CENTRAL_LAYER_Z = 0.0
const val UPPER_LAYER_Z = 166.0 const val UPPER_LAYER_Z = -166.0
const val LOWER_LAYER_Z = -180.0 const val LOWER_LAYER_Z = 180.0
/** /**
* Build map for the whole monitor * Build map for the whole monitor
@ -136,11 +136,11 @@ object Monitor {
.lineSequence() .lineSequence()
.mapNotNull { line -> .mapNotNull { line ->
if (line.startsWith(" ")) { if (line.startsWith(" ")) {
val split = line.trim().split("\\s+".toRegex()); val split = line.trim().split("\\s+".toRegex())
val detectorName = split[1]; val detectorName = split[1];
val x = split[4].toDouble() - 500; val x = split[4].toDouble() - 500
val y = split[5].toDouble() - 500; val y = split[5].toDouble() - 500
val z = split[6].toDouble() - 180; val z = 180 - split[6].toDouble()
SC16(detectorName, Point3D(x, y, z)) SC16(detectorName, Point3D(x, y, z))
} else { } else {
null null

View File

@ -6,53 +6,41 @@ import hep.dataforge.js.startApplication
import hep.dataforge.meta.buildMeta import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.withBottom import hep.dataforge.meta.withBottom
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.vis.js.editor.card
import hep.dataforge.vis.js.editor.objectTree import hep.dataforge.vis.js.editor.objectTree
import hep.dataforge.vis.js.editor.propertyEditor import hep.dataforge.vis.js.editor.propertyEditor
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY
import hep.dataforge.vis.spatial.Visual3DPlugin
import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.VisualObject3D
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.ThreePlugin
import hep.dataforge.vis.spatial.three.output import hep.dataforge.vis.spatial.three.output
import hep.dataforge.vis.spatial.three.threeSettings import hep.dataforge.vis.spatial.three.threeSettings
import hep.dataforge.vis.spatial.visible import hep.dataforge.vis.spatial.visible
import io.ktor.client.HttpClient
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
import io.ktor.client.request.get
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.html.js.button
import kotlinx.html.js.onClickFunction
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import kotlin.browser.document import kotlin.browser.document
import kotlin.dom.clear import kotlin.dom.clear
import kotlin.math.PI
private class GDMLDemoApp : Application { private class GDMLDemoApp : Application {
// /**
// * Handle mouse drag according to https://www.html5rocks.com/en/tutorials/file/dndfiles/
// */
// private fun handleDragOver(event: DragEvent) {
// event.stopPropagation()
// event.preventDefault()
// event.dataTransfer?.dropEffect = "copy"
// }
//
// /**
// * Load data from text file
// */
// private fun loadData(event: DragEvent, block: (name: String, data: String) -> Unit) {
// event.stopPropagation()
// event.preventDefault()
//
// val file = (event.dataTransfer?.files as FileList)[0]
// ?: throw RuntimeException("Failed to load file")
//
// FileReader().apply {
// onload = {
// val string = result as String
// block(file.name, string)
// }
// readAsText(file)
// }
// }
private val model = Model() private val model = Model()
private val connection = HttpClient{
install(JsonFeature) {
serializer = KotlinxSerializer(Visual3DPlugin.json)
}
}
override fun start(state: Map<String, Any>) { override fun start(state: Map<String, Any>) {
val context = Global.context("demo") {} val context = Global.context("demo") {}
@ -75,7 +63,25 @@ private class GDMLDemoApp : Application {
output.camera.layers.set(0) output.camera.layers.set(0)
output.camera.position.z = -2000.0 output.camera.position.z = -2000.0
output.camera.position.y = 500.0 output.camera.position.y = 500.0
settingsElement.threeSettings(output) settingsElement.threeSettings(output){
card("Events") {
button {
+"Next"
onClickFunction = {
GlobalScope.launch {
val event = connection.get<Event>("http://localhost:8080/event")
model.displayEvent(event)
}
}
}
button {
+"Clear"
onClickFunction = {
model.reset()
}
}
}
}
//tree.visualObjectTree(visual, editor::propertyEditor) //tree.visualObjectTree(visual, editor::propertyEditor)
treeElement.objectTree(NameToken("World"), visual) { treeElement.objectTree(NameToken("World"), visual) {
editorElement.propertyEditor(it) { item -> editorElement.propertyEditor(it) { item ->

View File

@ -11,24 +11,19 @@
<script type="text/javascript" src="main.bundle.js"></script> <script type="text/javascript" src="main.bundle.js"></script>
</head> </head>
<body class="testApp"> <body class="testApp">
<!--
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
title="Для загрузки данных в текстовом формате, надо перетащить файл сюда">
Загрузить данные
<br/>
(перетащить файл сюда)
</div>
-->
<div class="container"> <div class="container">
<h1>Muon monitor demo</h1> <h1>Muon monitor demo</h1>
</div> </div>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-lg-3" id="tree"></div> <div class="col-lg-3">
<div class="col-lg-6">
<div class="row" id ="settings"></div> <div class="row" id ="settings"></div>
<div class="row" id="canvas"></div> <div class="row" id ="tree"></div>
</div>
<div class="col-lg-6">
<div class="container" id = "canvas"></div>
</div> </div>
<div class="col-lg-3" id="editor"></div> <div class="col-lg-3" id="editor"></div>
</div> </div>

View File

@ -5,6 +5,7 @@ import hep.dataforge.vis.spatial.Visual3DPlugin
import io.ktor.application.Application import io.ktor.application.Application
import io.ktor.application.call import io.ktor.application.call
import io.ktor.application.install import io.ktor.application.install
import io.ktor.application.log
import io.ktor.features.CallLogging import io.ktor.features.CallLogging
import io.ktor.features.ContentNegotiation import io.ktor.features.ContentNegotiation
import io.ktor.features.DefaultHeaders import io.ktor.features.DefaultHeaders
@ -18,24 +19,28 @@ import io.ktor.server.cio.CIO
import io.ktor.server.engine.embeddedServer import io.ktor.server.engine.embeddedServer
import org.apache.commons.math3.random.JDKRandomGenerator import org.apache.commons.math3.random.JDKRandomGenerator
import ru.mipt.npm.muon.monitor.Model import ru.mipt.npm.muon.monitor.Model
import ru.mipt.npm.muon.monitor.sim.UniformTrackGenerator import ru.mipt.npm.muon.monitor.sim.Cos2TrackGenerator
import ru.mipt.npm.muon.monitor.sim.simulateOne import ru.mipt.npm.muon.monitor.sim.simulateOne
import java.awt.Desktop
import java.io.File import java.io.File
import java.net.URI
private val generator = Cos2TrackGenerator(JDKRandomGenerator(223))
fun Application.module() { fun Application.module() {
val currentDir = File(".").absoluteFile val currentDir = File(".").absoluteFile
environment.log.info("Current directory: $currentDir") environment.log.info("Current directory: $currentDir")
val generator = UniformTrackGenerator(JDKRandomGenerator(223))
install(DefaultHeaders) install(DefaultHeaders)
install(CallLogging) install(CallLogging)
install(ContentNegotiation) { install(ContentNegotiation) {
serialization(json = Visual3DPlugin.json) serialization(json = Visual3DPlugin.json)
} }
install(Routing) { install(Routing) {
get("/next") { get("/event") {
call.respond(generator.simulateOne()) val event = generator.simulateOne()
call.respond(event)
} }
get("/geometry") { get("/geometry") {
call.respond(Model.buildGeometry()) call.respond(Model.buildGeometry())
@ -44,6 +49,11 @@ fun Application.module() {
resources() resources()
} }
} }
try {
Desktop.getDesktop().browse(URI("http://localhost:8080/index.html"))
} catch (ex: Exception) {
log.error("Failed to launch browser", ex)
}
} }
fun main() { fun main() {

View File

@ -54,8 +54,8 @@ fun Vector3D.toPoint() = Point3D(x, y, z)
fun Line.toPoints(): List<Point3D> { fun Line.toPoints(): List<Point3D> {
val basePoint = basePlane.intersection(this) val basePoint = basePlane.intersection(this)
val bottom = basePoint.subtract(300.0, direction) val bottom = basePoint.subtract(2000.0, direction)
val top = basePoint.add(300.0, direction) val top = basePoint.add(2000.0, direction)
return listOf(bottom.toPoint(), top.toPoint()) return listOf(bottom.toPoint(), top.toPoint())
} }

View File

@ -11,13 +11,14 @@ import java.util.*
// minimal track length in detector // minimal track length in detector
val MINIMAL_TRACK_LENGTH = 10.0 internal const val MINIMAL_TRACK_LENGTH = 10.0
private val layerCache = HashMap<Double, Plane>() private val layerCache = HashMap<Double, Plane>()
fun findLayer(z: Double): Plane = layerCache.getOrPut(z) { fun findLayer(z: Double): Plane = layerCache.getOrPut(z) {
Plane(Vector3D(0.0, 0.0, z), Vector3D(0.0, 0.0, 1.0), Plane(
Vector3D(0.0, 0.0, z), Vector3D(0.0, 0.0, 1.0),
Monitor.GEOMETRY_TOLERANCE Monitor.GEOMETRY_TOLERANCE
) )
} }
@ -34,7 +35,7 @@ fun readEffs(): Map<String, Double> {
index = 0 index = 0
} else if (trimmed.isNotEmpty()) { } else if (trimmed.isNotEmpty()) {
val eff = trimmed.split(Regex("\\s+"))[1].toDouble() val eff = trimmed.split(Regex("\\s+"))[1].toDouble()
effMap.put("SC${detectorName}_${index}", eff) effMap["SC${detectorName}_${index}"] = eff
index++ index++
} }
} }
@ -42,8 +43,8 @@ fun readEffs(): Map<String, Double> {
} }
fun buildEventByTrack(track: Line, hitResolver: (Line) -> Collection<SC1> = defaultHitResolver): Event { fun buildEventByTrack(index: Int, track: Line, hitResolver: (Line) -> Collection<SC1> = defaultHitResolver): Event {
return Event(track.toPoints(), hitResolver(track).map { it.name }) return Event(index, track.toPoints(), hitResolver(track).map { it.name })
} }
val defaultHitResolver: (Line) -> Collection<SC1> = { track: Line -> val defaultHitResolver: (Line) -> Collection<SC1> = { track: Line ->

View File

@ -4,14 +4,18 @@ import org.apache.commons.math3.geometry.euclidean.threed.Line
import org.apache.commons.math3.random.RandomGenerator import org.apache.commons.math3.random.RandomGenerator
import ru.mipt.npm.muon.monitor.Event import ru.mipt.npm.muon.monitor.Event
import ru.mipt.npm.muon.monitor.Monitor.PIXEL_XY_SIZE import ru.mipt.npm.muon.monitor.Monitor.PIXEL_XY_SIZE
import kotlin.math.acos
import kotlin.math.pow
import kotlin.math.sin
private var counter = 0
/** /**
* Simulate single track and returns corresponding event * Simulate single track and returns corresponding event
*/ */
fun TrackGenerator.simulateOne(): Event { fun TrackGenerator.simulateOne(): Event {
val track = generate() val track = generate()
return buildEventByTrack(track) return buildEventByTrack(counter++, track)
} }
interface TrackGenerator { interface TrackGenerator {
@ -22,13 +26,17 @@ interface TrackGenerator {
/** /**
* A uniform generator with track bases distributed in square in central plane, uniform phi and cos theta * A uniform generator with track bases distributed in square in central plane, uniform phi and cos theta
*/ */
class UniformTrackGenerator(override val rnd: RandomGenerator, val maxX: Double = 4 * PIXEL_XY_SIZE, val maxY: Double = 4 * PIXEL_XY_SIZE) : class UniformTrackGenerator(
override val rnd: RandomGenerator,
val maxX: Double = 4 * PIXEL_XY_SIZE,
val maxY: Double = 4 * PIXEL_XY_SIZE
) :
TrackGenerator { TrackGenerator {
override fun generate(): Line { override fun generate(): Line {
val x = (1 - rnd.nextDouble() * 2.0) * maxX val x = (1 - rnd.nextDouble() * 2.0) * maxX
val y = (1 - rnd.nextDouble() * 2.0) * maxY val y = (1 - rnd.nextDouble() * 2.0) * maxY
val phi = (1 - rnd.nextDouble() * 2.0) * Math.PI val phi = (1 - rnd.nextDouble() * 2.0) * Math.PI
val theta = Math.PI / 2 - Math.acos(rnd.nextDouble()) val theta = Math.PI / 2 - acos(rnd.nextDouble())
return makeTrack(x, y, theta, phi) return makeTrack(x, y, theta, phi)
} }
} }
@ -63,10 +71,10 @@ class Cos2TrackGenerator(
for (i in 0..500) { for (i in 0..500) {
val thetaCandidate = Math.acos(rnd.nextDouble()) val thetaCandidate = acos(rnd.nextDouble())
val u = rnd.nextDouble() val u = rnd.nextDouble()
val sin = Math.sin(thetaCandidate) val sin = sin(thetaCandidate)
if (u < Math.pow(sin, power) / sin) { if (u < sin.pow(power) / sin) {
return makeTrack(x, y, thetaCandidate, phi) return makeTrack(x, y, thetaCandidate, phi)
} }
} }