RC 0.1.0
This commit is contained in:
parent
dac794b8ca
commit
d36542ac5b
@ -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()) {
|
||||||
} else {
|
if(child!= null) {
|
||||||
set(key.asName(), child)
|
addStatic(child)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
set(key.toName(), child)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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() }
|
||||||
|
@ -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)
|
||||||
|
@ -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")
|
||||||
}
|
//}
|
@ -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 = "]")
|
||||||
}
|
}
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 ->
|
||||||
|
@ -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="row" id ="settings"></div>
|
||||||
|
<div class="row" id ="tree"></div>
|
||||||
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="row" id="settings"></div>
|
<div class="container" id = "canvas"></div>
|
||||||
<div class="row" id="canvas"></div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3" id="editor"></div>
|
<div class="col-lg-3" id="editor"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -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,34 +19,43 @@ 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())
|
||||||
}
|
}
|
||||||
static("/") {
|
static("/") {
|
||||||
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() {
|
||||||
embeddedServer(CIO, 8080,host = "localhost", module = Application::module).start(wait = true)
|
embeddedServer(CIO, 8080, host = "localhost", module = Application::module).start(wait = true)
|
||||||
}
|
}
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 ->
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user