GDML model in progress

This commit is contained in:
Alexander Nozik 2019-04-02 20:24:31 +03:00
parent 9a7fcfe9c6
commit 953bafb02e
15 changed files with 358 additions and 31 deletions

View File

@ -13,7 +13,7 @@ buildscript {
val dokkaVersion: String by rootProject.extra("0.9.17") val dokkaVersion: String by rootProject.extra("0.9.17")
val serializationVersion: String by rootProject.extra("0.10.0") val serializationVersion: String by rootProject.extra("0.10.0")
val dataforgeVersion: String by rootProject.extra("0.1.2-dev-2") val dataforgeVersion: String by rootProject.extra("0.1.2-dev-3")
repositories { repositories {
jcenter() jcenter()

View File

@ -8,11 +8,16 @@ plugins {
id("org.jetbrains.kotlin.frontend") id("org.jetbrains.kotlin.frontend")
} }
repositories{
maven ("https://dl.bintray.com/orangy/maven" )
}
val kotlinVersion: String by rootProject.extra val kotlinVersion: String by rootProject.extra
dependencies { dependencies {
api(project(":dataforge-vis-spatial")) implementation(project(":dataforge-vis-spatial"))
implementation("info.laht.threekt:threejs-wrapper:0.88-npm-2") implementation("info.laht.threekt:threejs-wrapper:0.88-npm-2")
//implementation("org.jetbrains.kotlinx:kotlinx-files-js:0.1.0-dev-27")
testCompile("org.jetbrains.kotlin:kotlin-test-js:$kotlinVersion") testCompile("org.jetbrains.kotlin:kotlin-test-js:$kotlinVersion")
} }
@ -22,6 +27,9 @@ configure<KotlinFrontendExtension> {
configure<NpmExtension> { configure<NpmExtension> {
dependency("three-full") dependency("three-full")
dependency("style-loader") dependency("style-loader")
// dependency("fs-remote")
// dependency("path")
// dependency("text-encoding")
devDependency("karma") devDependency("karma")
} }

View File

@ -6,7 +6,8 @@ import hep.dataforge.vis.ApplicationBase
import hep.dataforge.vis.DisplayGroup import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.require import hep.dataforge.vis.require
import hep.dataforge.vis.spatial.jsroot.JSRootPlugin import hep.dataforge.vis.spatial.jsroot.JSRootPlugin
import hep.dataforge.vis.spatial.jsroot.jsRoot import hep.dataforge.vis.spatial.jsroot.jsRootGeometry
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
@ -65,7 +66,7 @@ class ThreeDemoApp : ApplicationBase() {
point(-50, 50, -50) point(-50, 50, -50)
point(50, -50, -50) point(50, -50, -50)
} }
jsRoot { jsRootGeometry {
y = 110.0 y = 110.0
shape = box(50, 50, 50) shape = box(50, 50, 50)
color(12285) color(12285)

View File

@ -0,0 +1,40 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.Config
class GDML {
private var defines: List<GDMLDefine> = emptyList()
private var solids: Map<String, GDMLSolid> = emptyMap()
fun define(block: GDMLDefineBuilder.() -> Unit) {
defines = GDMLDefineBuilder().apply(block).defines
}
fun solids(block: GDMLSolidBuilder.() -> Unit) {
solids = GDMLSolidBuilder().apply(block).solids
}
}
class GDMLDefineBuilder {
internal val defines = ArrayList<GDMLDefine>()
fun position(block: GDMLPosition.() -> Unit) {
defines.add(GDMLPosition(Config()).apply(block))
}
fun rotation(block: GDMLRotation.() -> Unit) {
defines.add(GDMLRotation(Config()).apply(block))
}
}
class GDMLSolidBuilder {
internal val solids = HashMap<String, GDMLSolid>()
private fun put(solid: GDMLSolid) {
solids[solid.pName!!] = solid
}
fun box(block: GDMLBox.() -> Unit) = put(GDMLBox.build(block))
fun tube(block: GDMLTube.() -> Unit) = put(GDMLTube.build(block))
fun xtru(block: GDMLXtru.() -> Unit) = put(GDMLXtru.build(block))
}

View File

@ -0,0 +1,106 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.*
sealed class GDMLNode(override val config: Config) : Specification {
var pName by string()
}
sealed class GDMLDefine(config: Config) : GDMLNode(config)
class GDMLPosition(config: Config) : GDMLDefine(config) {
var x by number(0f).float
var y by number(0f).float
var z by number(0f).float
var unit by string("cm")
}
class GDMLRotation(config: Config) : GDMLDefine(config) {
var x by number(0f).float
var y by number(0f).float
var z by number(0f).float
var unit by string("deg")
}
sealed class GDMLSolid(config: Config) : GDMLNode(config) {
abstract val type: String
}
class GDMLBox(config: Config) : GDMLSolid(config) {
override val type: String = "box"
var pDx by number().double
var pDy by number().double
var pDz by number().double
companion object : SpecificationCompanion<GDMLBox> {
override fun wrap(config: Config): GDMLBox = GDMLBox(config)
}
}
class GDMLTube(config: Config) : GDMLSolid(config) {
override val type: String = "tube"
var pRMin by number().double
var pRMax by number().double
var pDz by number().double
var pSPhi by number().double
var pDPhi by number().double
companion object : SpecificationCompanion<GDMLTube> {
override fun wrap(config: Config): GDMLTube = GDMLTube(config)
}
}
class GDMLXtru(config: Config) : GDMLSolid(config) {
override val type: String = "xtru"
class TwoDimVertex(val x: Double, val y: Double)
class Section(override val config: Config) : Specification {
var zOrder by number().int
var zPosition by number().double
var xOffsset by number(0.0).double
var yOffset by number(0.0).double
var scalingFactor by number(1.0).double
companion object : SpecificationCompanion<Section> {
override fun wrap(config: Config): Section = Section(config)
}
}
val verteces
get() = config.getAll("twoDimVertex").values.map {
val x = it.node["x"].double!!
val y = it.node["y"].double!!
TwoDimVertex(x, y)
}
val sections get() = config.getAll("section").values.map { Section(it.node!!) }
fun vertex(x: Double, y: Double) {
config.append("twoDimVertex", TwoDimVertex(x, y))
}
fun section(index: Int, z: Double, block: Section.() -> Unit) {
config["section[$index]"] = Section.build(block).apply { zOrder = index; zPosition = z }
}
companion object : SpecificationCompanion<GDMLXtru> {
override fun wrap(config: Config): GDMLXtru = GDMLXtru(config)
}
}
class GDMLUnion(config: Config) : GDMLSolid(config) {
override val type: String = "union"
val first by node()
val second by node()
companion object : SpecificationCompanion<GDMLUnion> {
override fun wrap(config: Config): GDMLUnion = GDMLUnion(config)
}
}

View File

@ -0,0 +1,35 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.context.AbstractPlugin
import hep.dataforge.context.Context
import hep.dataforge.context.PluginFactory
import hep.dataforge.context.PluginTag
import hep.dataforge.vis.spatial.ThreePlugin
class GDMLPlugin : AbstractPlugin() {
override val tag: PluginTag get() = GDMLPlugin.tag
override fun dependsOn() = listOf(ThreePlugin)
override fun attach(context: Context) {
super.attach(context)
// context.plugins.get<ThreePlugin>()?.factories?.apply {
// this["jsRoot.geometry".toName()] = ThreeJSRootGeometryFactory
// this["jsRoot.object".toName()] = ThreeJSRootObjectFactory
// }
}
override fun detach() {
// context.plugins.get<ThreePlugin>()?.factories?.apply {
// remove("jsRoot.geometry".toName())
// remove("jsRoot.object".toName())
// }
super.detach()
}
companion object : PluginFactory<GDMLPlugin> {
override val tag = PluginTag("vis.gdml", "hep.dataforge")
override val type = GDMLPlugin::class
override fun invoke() = GDMLPlugin()
}
}

View File

@ -0,0 +1,73 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.Meta
import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.toDynamic
import hep.dataforge.meta.values
import hep.dataforge.vis.DisplayLeaf
import hep.dataforge.vis.DisplayObject
import hep.dataforge.vis.int
import hep.dataforge.vis.spatial.MeshThreeFactory
import hep.dataforge.vis.spatial.jsroot.createGeometry
import hep.dataforge.vis.spatial.jsroot.createTubeBuffer
import info.laht.threekt.core.BufferGeometry
class GDMLShape(parent: DisplayObject?, meta: Meta, val shape: GDMLSolid) :
DisplayLeaf(parent, "$TYPE.${shape.type}", meta) {
var facesLimit by int(0)
companion object {
const val TYPE = "geometry.3d.gdml"
}
}
object ThreeGDMLFactory : MeshThreeFactory<GDMLShape>(GDMLShape::class) {
//TODO fix ineffective conversion
private fun Meta?.toJsRoot() = this?.let {
buildMeta {
values().forEach { (name, value) ->
name.toString().replaceFirst("p", "f") to value
}
}
}
override fun buildGeometry(obj: GDMLShape): BufferGeometry {
return when (obj.shape) {
is GDMLBox -> createTubeBuffer(
obj.shape.config.toJsRoot(),
obj.facesLimit
)
is GDMLTube -> createTubeBuffer(
obj.shape.config.toJsRoot(),
obj.facesLimit
)
is GDMLXtru -> {
val meta = buildMeta {
val vertices = obj.shape.verteces
val zs = obj.shape.sections.sortedBy { it.zOrder!! }
"fNz" to zs.size
"fNvert" to vertices.size
"_typename" to "TGeoXtru"
"fX" to vertices.map { it.x }
"fY" to vertices.map { it.y }
"fX0" to zs.map { it.xOffsset }
"fY0" to zs.map { it.yOffset }
"fZ" to zs.map { it.zPosition!! }
"fScale" to zs.map { it.scalingFactor }
}
createGeometry(meta.toDynamic(), obj.facesLimit)
}
// is GDMLUnion -> {
// val meta = buildMeta {
// "fNode.fLeft" to obj.shape.first.toJsRoot()
// "fNode.fRight" to obj.shape.second.toJsRoot()
// "fNode._typename" to "TGeoUnion"
// }
// createGeometry(meta.toDynamic(), obj.facesLimit)
// }
}
}
}

View File

@ -1,12 +1,18 @@
package hep.dataforge.vis.spatial.jsroot package hep.dataforge.vis.spatial.jsroot
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.vis.ApplicationBase import hep.dataforge.vis.ApplicationBase
import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.require import hep.dataforge.vis.require
import hep.dataforge.vis.spatial.ThreeOutput import hep.dataforge.vis.spatial.ThreeOutput
import hep.dataforge.vis.spatial.render import hep.dataforge.vis.spatial.render
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.events.Event
import org.w3c.files.FileList
import org.w3c.files.FileReader
import org.w3c.files.get
import kotlin.browser.document import kotlin.browser.document
import kotlin.dom.clear
class JSRootDemoApp : ApplicationBase() { class JSRootDemoApp : ApplicationBase() {
@ -23,16 +29,52 @@ class JSRootDemoApp : ApplicationBase() {
Global.plugins.load(JSRootPlugin) Global.plugins.load(JSRootPlugin)
val renderer = ThreeOutput(Global)
renderer.start(document.getElementById("canvas")!!)
println("started")
lateinit var group: DisplayGroup
renderer.render { (document.getElementById("drop_zone") as? HTMLDivElement)?.apply {
jsRoot ("./geofile_full.json") addEventListener("dragover", { handleDragOver(it) }, false)
addEventListener("drop", { loadData(it) }, false)
} }
}
/**
* Handle mouse drag according to https://www.html5rocks.com/en/tutorials/file/dndfiles/
*/
private fun handleDragOver(event: Event) {
event.stopPropagation()
event.preventDefault()
event.asDynamic().dataTransfer.dropEffect = "copy"
}
/**
* Load data from text file
*/
private fun loadData(event: Event) {
event.stopPropagation()
event.preventDefault()
val file = (event.asDynamic().dataTransfer.files as FileList)[0]
?: throw RuntimeException("Failed to load file");
FileReader().apply {
onload = {
val string = result as String
val renderer = ThreeOutput(Global)
val canvas = document.getElementById("canvas")!!
canvas.clear()
renderer.start(canvas)
println("started")
renderer.render {
val json = JSON.parse<Any>(string).asDynamic()
val obj = json.fVolumes.arr[0]
JSRootObject(this, EmptyMeta, obj).also { addChild(it) }
}
}
readAsText(file)
}
} }
override fun dispose() = emptyMap<String, Any>()//mapOf("lines" to presenter.dispose()) override fun dispose() = emptyMap<String, Any>()//mapOf("lines" to presenter.dispose())

View File

@ -8,4 +8,10 @@ import info.laht.threekt.core.Object3D
external fun createGeometry(shape: dynamic, limit: Int): BufferGeometry external fun createGeometry(shape: dynamic, limit: Int): BufferGeometry
external fun createCubeBuffer(shape: dynamic, limit: Int): BufferGeometry
external fun createTubeBuffer(shape: dynamic, limit: Int): BufferGeometry
external fun createXtruBuffer(shape: dynamic, limit: Int): BufferGeometry
external fun build(obj: dynamic, opt: dynamic): Object3D external fun build(obj: dynamic, opt: dynamic): Object3D

View File

@ -53,7 +53,7 @@ class JSRootGeometry(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, T
} }
} }
fun DisplayGroup.jsRoot(meta: Meta = EmptyMeta, action: JSRootGeometry.() -> Unit = {}) = fun DisplayGroup.jsRootGeometry(meta: Meta = EmptyMeta, action: JSRootGeometry.() -> Unit = {}) =
JSRootGeometry(this, meta).apply(action).also { addChild(it) } JSRootGeometry(this, meta).apply(action).also { addChild(it) }
//fun Meta.toDynamic(): dynamic { //fun Meta.toDynamic(): dynamic {
@ -74,7 +74,7 @@ fun DisplayGroup.jsRoot(meta: Meta = EmptyMeta, action: JSRootGeometry.() -> Uni
//} //}
object ThreeJSRootFactory : MeshThreeFactory<JSRootGeometry>(JSRootGeometry::class) { object ThreeJSRootGeometryFactory : MeshThreeFactory<JSRootGeometry>(JSRootGeometry::class) {
override fun buildGeometry(obj: JSRootGeometry): BufferGeometry { override fun buildGeometry(obj: JSRootGeometry): BufferGeometry {
val shapeMeta = obj.shape?.toDynamic() ?: error("The shape not defined") val shapeMeta = obj.shape?.toDynamic() ?: error("The shape not defined")
return createGeometry(shapeMeta, obj.facesLimit) return createGeometry(shapeMeta, obj.facesLimit)

View File

@ -1,6 +1,5 @@
package hep.dataforge.vis.spatial.jsroot package hep.dataforge.vis.spatial.jsroot
import hep.dataforge.meta.DynamicMeta
import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.toDynamic import hep.dataforge.meta.toDynamic
@ -11,9 +10,8 @@ import hep.dataforge.vis.node
import hep.dataforge.vis.spatial.ThreeFactory import hep.dataforge.vis.spatial.ThreeFactory
import info.laht.threekt.core.Object3D import info.laht.threekt.core.Object3D
class JSRootObject(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) { class JSRootObject(parent: DisplayObject?, meta: Meta, val data: dynamic) : DisplayLeaf(parent, TYPE, meta) {
var data by node()
var options by node() var options by node()
companion object { companion object {
@ -21,17 +19,16 @@ class JSRootObject(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYP
} }
} }
object JSRootObjectFactory : ThreeFactory<JSRootObject> { object ThreeJSRootObjectFactory : ThreeFactory<JSRootObject> {
override val type = JSRootObject::class override val type = JSRootObject::class
override fun invoke(obj: JSRootObject): Object3D { override fun invoke(obj: JSRootObject): Object3D {
return build(obj.data?.toDynamic(), obj.options?.toDynamic()) return build(obj.data, obj.options?.toDynamic())
} }
} }
fun DisplayGroup.jsRoot(path: String) { fun DisplayGroup.jsRootObject(str: String) {
JSRootObject(this, EmptyMeta).apply{ val json = JSON.parse<Any>(str)
data = DynamicMeta(hep.dataforge.vis.require(path)) JSRootObject(this, EmptyMeta, json).also { addChild(it) }
}.also { addChild(it) }
} }

View File

@ -14,7 +14,18 @@ class JSRootPlugin : AbstractPlugin() {
override fun attach(context: Context) { override fun attach(context: Context) {
super.attach(context) super.attach(context)
context.plugins.get<ThreePlugin>()?.factories?.set("ThreeJSRootFactory".toName(), ThreeJSRootFactory) context.plugins.get<ThreePlugin>()?.factories?.apply {
this["jsRoot.geometry".toName()] = ThreeJSRootGeometryFactory
this["jsRoot.object".toName()] = ThreeJSRootObjectFactory
}
}
override fun detach() {
context.plugins.get<ThreePlugin>()?.factories?.apply {
remove("jsRoot.geometry".toName())
remove("jsRoot.object".toName())
}
super.detach()
} }
companion object: PluginFactory<JSRootPlugin> { companion object: PluginFactory<JSRootPlugin> {

View File

@ -3428,7 +3428,7 @@
obj = null; obj = null;
} }
if (opt.composite && shape && (shape._typename == 'TGeoCompositeShape') && shape.fNode) if (opt.composite && shape && (shape._typename === 'TGeoCompositeShape') && shape.fNode)
obj = GEO.buildCompositeVolume(shape); obj = GEO.buildCompositeVolume(shape);
if (!obj && shape) if (!obj && shape)

View File

@ -4,7 +4,7 @@
<title>Three js demo for particle physics</title> <title>Three js demo for particle physics</title>
<style> <style>
body { body {
margin: 0px; margin: 0;
overflow: hidden; overflow: hidden;
} }
</style> </style>
@ -14,9 +14,15 @@
<!--<script type="text/javascript" src="js/ThreeCSG.js"></script>--> <!--<script type="text/javascript" src="js/ThreeCSG.js"></script>-->
<!--<script type="text/javascript" src="js/JSRootCore.js"></script>--> <!--<script type="text/javascript" src="js/JSRootCore.js"></script>-->
<!--<script type="text/javascript" src="js/JSRootGeoBase.js"></script>--> <!--<script type="text/javascript" src="js/JSRootGeoBase.js"></script>-->
<script type="text/javascript" language="JavaScript" src="main.bundle.js"></script> <script type="text/javascript" src="main.bundle.js"></script>
</head> </head>
<body class="testApp"> <body class="testApp">
<div id="drop_zone" data-toggle="tooltip" data-placement="right"
title="Для загрузки данных в текстовом формате, надо перетащить файл сюда">
Загрузить данные
<br/>
(перетащить файл сюда)
</div>
<h1>Demo canvas</h1> <h1>Demo canvas</h1>
<div id="canvas"></div> <div id="canvas"></div>
</body> </body>

View File

@ -25,3 +25,5 @@ include(
":dataforge-vis-spatial-fx", ":dataforge-vis-spatial-fx",
":dataforge-vis-spatial-js" ":dataforge-vis-spatial-js"
) )
includeBuild("../dataforge-core")