Update architecture

This commit is contained in:
Alexander Nozik 2019-03-25 22:12:22 +03:00
parent 4865c76158
commit d874c3cdd6
15 changed files with 227 additions and 138 deletions

View File

@ -9,7 +9,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.1-dev-5") val dataforgeVersion: String by rootProject.extra("0.1.2-dev-1")
repositories { repositories {
jcenter() jcenter()
@ -40,6 +40,7 @@ allprojects {
jcenter() jcenter()
maven("https://kotlin.bintray.com/kotlinx") maven("https://kotlin.bintray.com/kotlinx")
maven("http://npm.mipt.ru:8081/artifactory/gradle-dev") maven("http://npm.mipt.ru:8081/artifactory/gradle-dev")
mavenLocal()
} }
group = "hep.dataforge" group = "hep.dataforge"

View File

@ -11,19 +11,19 @@ kotlin {
sourceSets { sourceSets {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
api("hep.dataforge:dataforge-io:$dataforgeVersion") api("hep.dataforge:dataforge-output:$dataforgeVersion")
api("hep.dataforge:dataforge-io-metadata:$dataforgeVersion") //api("hep.dataforge:dataforge-output-metadata:$dataforgeVersion")
} }
} }
val jvmMain by getting { val jvmMain by getting {
dependencies { dependencies {
api("hep.dataforge:dataforge-io-jvm:$dataforgeVersion") api("hep.dataforge:dataforge-output-jvm:$dataforgeVersion")
//api("no.tornado:tornadofx:1.7.18") //api("no.tornado:tornadofx:1.7.18")
} }
} }
val jsMain by getting { val jsMain by getting {
dependencies { dependencies {
api("hep.dataforge:dataforge-io-js:$dataforgeVersion") api("hep.dataforge:dataforge-output-js:$dataforgeVersion")
} }
} }
} }

View File

@ -1,12 +1,14 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.context.members
import hep.dataforge.meta.number import hep.dataforge.meta.number
import hep.dataforge.meta.set import hep.dataforge.meta.set
import hep.dataforge.vis.ApplicationBase 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.gdml.gdml import hep.dataforge.vis.spatial.jsroot.JSRootPlugin
import hep.dataforge.vis.spatial.jsroot.jsRoot
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive import kotlinx.coroutines.isActive
@ -22,6 +24,23 @@ class ThreeDemoApp : ApplicationBase() {
override fun start(state: Map<String, Any>) { override fun start(state: Map<String, Any>) {
require("JSRootGeoBase.js") require("JSRootGeoBase.js")
//TODO remove after DI fix
Global.plugins.load(ThreePlugin())
Global.plugins.load(JSRootPlugin())
// Global.plugins.load(JSRootPlugin)
println(Global.plugins.count())
Global.plugins.forEach {
println(it)
}
Global.members<ThreeFactory<*>>(ThreeFactory.TYPE).forEach {
println(it)
}
val renderer = ThreeOutput(Global) val renderer = ThreeOutput(Global)
renderer.start(document.getElementById("canvas")!!) renderer.start(document.getElementById("canvas")!!)
println("started") println("started")
@ -53,7 +72,7 @@ class ThreeDemoApp : ApplicationBase() {
// point(-50, -50, 50) // point(-50, -50, 50)
// point(-50, 50, 50) // point(-50, 50, 50)
// } // }
gdml { jsRoot {
y = 110.0 y = 110.0
shape = box(50, 50, 50) shape = box(50, 50, 50)
} }

View File

@ -0,0 +1,100 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.boolean
import hep.dataforge.provider.Type
import hep.dataforge.vis.DisplayObject
import hep.dataforge.vis.get
import hep.dataforge.vis.onChange
import hep.dataforge.vis.spatial.ThreeFactory.Companion.TYPE
import hep.dataforge.vis.spatial.ThreeFactory.Companion.buildMesh
import hep.dataforge.vis.spatial.ThreeFactory.Companion.updateMesh
import hep.dataforge.vis.spatial.three.ConvexGeometry
import hep.dataforge.vis.spatial.three.EdgesGeometry
import hep.dataforge.vis.spatial.three.euler
import info.laht.threekt.core.BufferGeometry
import info.laht.threekt.core.Object3D
import info.laht.threekt.geometries.BoxBufferGeometry
import info.laht.threekt.geometries.WireframeGeometry
import info.laht.threekt.math.Vector3
import info.laht.threekt.objects.LineSegments
import info.laht.threekt.objects.Mesh
import kotlin.reflect.KClass
internal val DisplayObject.material get() = this["color"].material()
/**
* Builder and updater for three.js object
*/
@Type(TYPE)
interface ThreeFactory<T : DisplayObject> {
val type: KClass<out T>
operator fun invoke(obj: T): Object3D
companion object {
const val TYPE = "threeFactory"
/**
* Update position, rotation and visibility
*/
internal fun updatePosition(obj: DisplayObject, target: Object3D) {
target.apply {
position.set(obj.x, obj.y, obj.z)
setRotationFromEuler(obj.euler)
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
visible = obj.visible
}
}
internal fun buildMesh(obj: DisplayObject, geometry: BufferGeometry): Mesh {
val mesh = Mesh(geometry, obj.material)
if (obj["edges.enabled"]?.boolean != false) {
val material = obj["edges.material"]?.material() ?: Materials.DEFAULT
mesh.add(LineSegments(EdgesGeometry(mesh.geometry as BufferGeometry), material))
}
if (obj["wireframe.enabled"]?.boolean == true) {
val material = obj["edges.material"]?.material() ?: Materials.DEFAULT
mesh.add(LineSegments(WireframeGeometry(mesh.geometry as BufferGeometry), material))
}
return mesh
}
internal fun updateMesh(obj: DisplayObject, geometry: BufferGeometry, mesh: Mesh) {
mesh.geometry = geometry
mesh.material = obj.material
}
}
}
abstract class MeshThreeFactory<T : DisplayObject>(override val type: KClass<out T>) : ThreeFactory<T> {
/**
* Build an object
*/
abstract fun buildGeometry(obj: T): BufferGeometry
override fun invoke(obj: T): Mesh {
val geometry = buildGeometry(obj)
val mesh = buildMesh(obj, geometry)
ThreeFactory.updatePosition(obj, mesh)
obj.onChange(this) { _, _, _ ->
ThreeFactory.updatePosition(obj, mesh)
updateMesh(obj, buildGeometry(obj), mesh)
}
return mesh
}
}
object ThreeBoxFactory : MeshThreeFactory<Box>(Box::class) {
override fun buildGeometry(obj: Box) =
BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
}
fun Point3D.asVector(): Vector3 = this.asDynamic() as Vector3
object ThreeConvexFactory : MeshThreeFactory<Convex>(Convex::class) {
override fun buildGeometry(obj: Convex) =
ConvexGeometry(obj.points.map { it.asVector() }.toTypedArray())
}

View File

@ -1,87 +0,0 @@
package hep.dataforge.vis.spatial
import hep.dataforge.vis.DisplayObject
import hep.dataforge.vis.get
import hep.dataforge.vis.onChange
import hep.dataforge.vis.spatial.three.ConvexGeometry
import hep.dataforge.vis.spatial.three.EdgesGeometry
import hep.dataforge.vis.spatial.three.euler
import info.laht.threekt.core.Object3D
import info.laht.threekt.geometries.BoxBufferGeometry
import info.laht.threekt.math.Vector3
import info.laht.threekt.objects.LineSegments
import info.laht.threekt.objects.Mesh
/**
* Builder and updater for three.js object
*/
interface ThreeObjectBuilder<in T : DisplayObject> {
operator fun invoke(obj: T): Object3D
companion object {
/**
* Update position, rotation and visibility
*/
internal fun updatePosition(obj: DisplayObject, target: Object3D) {
target.apply {
position.set(obj.x, obj.y, obj.z)
setRotationFromEuler(obj.euler)
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
visible = obj.visible
}
}
}
}
abstract class GenericThreeBuilder<in T : DisplayObject, R : Object3D> : ThreeObjectBuilder<T> {
/**
* Build an object
*/
abstract fun build(obj: T): R
/**
* Update an object
*/
abstract fun update(obj: T, target: R)
override fun invoke(obj: T): R {
val target = build(obj)
ThreeObjectBuilder.updatePosition(obj, target)
obj.onChange(this) { _, _, _ ->
ThreeObjectBuilder.updatePosition(obj, target)
update(obj, target)
}
return target
}
}
object ThreeBoxBuilder : GenericThreeBuilder<Box, Mesh>() {
override fun build(obj: Box): Mesh {
val geometry = BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
return Mesh(geometry, obj["color"].material()).also { mesh ->
mesh.add(LineSegments(EdgesGeometry(geometry), Materials.DEFAULT))
}
}
override fun update(obj: Box, target: Mesh) {
target.geometry = BoxBufferGeometry(obj.xSize, obj.ySize, obj.zSize)
target.material = obj["color"].material()
}
}
fun Point3D.asVector(): Vector3 = this.asDynamic() as Vector3
object ThreeConvexBuilder: GenericThreeBuilder<Convex,Mesh>(){
override fun build(obj: Convex): Mesh {
val geometry = ConvexGeometry(obj.points.map { it.asVector() }.toTypedArray())
return Mesh(geometry, obj["color"].material()).also { mesh ->
mesh.add(LineSegments(EdgesGeometry(geometry), Materials.DEFAULT))
}
}
override fun update(obj: Convex, target: Mesh) {
target.geometry = ConvexGeometry(obj.points.map { it.asVector() }.toTypedArray())
target.material = obj["color"].material()
}
}

View File

@ -1,12 +1,11 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.context.Context import hep.dataforge.context.Context
import hep.dataforge.io.Output import hep.dataforge.context.members
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.output.Output
import hep.dataforge.vis.DisplayGroup import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.DisplayObject import hep.dataforge.vis.DisplayObject
import hep.dataforge.vis.spatial.gdml.GDMLObject
import hep.dataforge.vis.spatial.gdml.ThreeGDMLBuilder
import hep.dataforge.vis.spatial.three.Group import hep.dataforge.vis.spatial.three.Group
import info.laht.threekt.WebGLRenderer import info.laht.threekt.WebGLRenderer
import info.laht.threekt.cameras.PerspectiveCamera import info.laht.threekt.cameras.PerspectiveCamera
@ -17,6 +16,7 @@ import info.laht.threekt.math.ColorConstants
import info.laht.threekt.scenes.Scene import info.laht.threekt.scenes.Scene
import org.w3c.dom.Element import org.w3c.dom.Element
import kotlin.browser.window import kotlin.browser.window
import kotlin.reflect.KClass
class ThreeOutput(override val context: Context) : Output<DisplayObject> { class ThreeOutput(override val context: Context) : Output<DisplayObject> {
@ -65,15 +65,19 @@ class ThreeOutput(override val context: Context) : Output<DisplayObject> {
private fun buildNode(obj: DisplayObject): Object3D? { private fun buildNode(obj: DisplayObject): Object3D? {
return when (obj) { return when (obj) {
is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) }).apply { is DisplayGroup -> Group(obj.children.mapNotNull { buildNode(it) }).apply {
ThreeObjectBuilder.updatePosition(obj, this) ThreeFactory.updatePosition(obj, this)
} }
is Box -> ThreeBoxBuilder(obj) //is Box -> ThreeBoxFactory(obj)
is GDMLObject -> ThreeGDMLBuilder(obj) //is JSRootObject -> ThreeJSRootFactory(obj)
//is Convex -> ThreeConvexBuilder(obj) //is Convex -> ThreeConvexFactory(obj)
else -> null else -> findFactory(obj::class)?.invoke(obj)?: error("Factory not found")
} }
} }
private fun <T : DisplayObject> findFactory(type: KClass<out T>): ThreeFactory<T>? {
return context.members<ThreeFactory<*>>(ThreeFactory.TYPE).find { it.type == type } as? ThreeFactory<T>?
}
override fun render(obj: DisplayObject, meta: Meta) { override fun render(obj: DisplayObject, meta: Meta) {
buildNode(obj)?.let { buildNode(obj)?.let {
scene.add(it) scene.add(it)

View File

@ -0,0 +1,38 @@
package hep.dataforge.vis.spatial
import hep.dataforge.context.AbstractPlugin
import hep.dataforge.context.PluginFactory
import hep.dataforge.context.PluginTag
import hep.dataforge.names.Name
import hep.dataforge.names.toName
class ThreePlugin : AbstractPlugin() {
override val tag: PluginTag get() = ThreePlugin.tag
val factories = HashMap<Name, ThreeFactory<*>>()
init {
factories["box".toName()] = ThreeBoxFactory
factories["convex".toName()] = ThreeConvexFactory
}
override fun listTop(target: String): Sequence<Name> {
return when (target) {
ThreeFactory.TYPE -> factories.keys.asSequence()
else -> return super.listTop(target)
}
}
override fun provideTop(target: String, name: Name): Any? {
return when (target) {
ThreeFactory.TYPE -> factories[name]
else -> return super.provideTop(target, name)
}
}
companion object : PluginFactory<ThreePlugin> {
override val tag = PluginTag("vis.three", "hep.dataforge")
override val type = ThreePlugin::class
override fun build() = ThreePlugin()
}
}

View File

@ -1,7 +0,0 @@
@file:JsModule("JSRootGeoBase.js")
@file:JsNonModule
package hep.dataforge.vis.spatial.gdml
import info.laht.threekt.core.Geometry
external fun createGeometry(shape: dynamic, limit: Int): Geometry

View File

@ -0,0 +1,8 @@
@file:JsModule("JSRootGeoBase.js")
@file:JsNonModule
package hep.dataforge.vis.spatial.jsroot
import info.laht.threekt.core.BufferGeometry
external fun createGeometry(shape: dynamic, limit: Int): BufferGeometry

View File

@ -1,18 +1,14 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial.jsroot
import hep.dataforge.meta.EmptyMeta import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.buildMeta import hep.dataforge.meta.buildMeta
import hep.dataforge.vis.* import hep.dataforge.vis.*
import hep.dataforge.vis.spatial.GenericThreeBuilder import hep.dataforge.vis.spatial.MeshThreeFactory
import hep.dataforge.vis.spatial.Materials import info.laht.threekt.core.BufferGeometry
import hep.dataforge.vis.spatial.material
import hep.dataforge.vis.spatial.three.EdgesGeometry
import info.laht.threekt.objects.LineSegments
import info.laht.threekt.objects.Mesh
class GDMLObject(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) { class JSRootObject(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta) {
var shape by node() var shape by node()
@ -45,6 +41,9 @@ class GDMLObject(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE,
"fNode._typename" to "TGeoSubtraction" "fNode._typename" to "TGeoSubtraction"
} }
/**
* Intersect two GDML geometries
*/
infix fun Meta.intersect(other: Meta) = buildMeta { infix fun Meta.intersect(other: Meta) = buildMeta {
"fNode.fLeft" to this "fNode.fLeft" to this
"fNode.fRight" to other "fNode.fRight" to other
@ -52,13 +51,12 @@ class GDMLObject(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE,
} }
companion object { companion object {
const val TYPE = "geometry.spatial.gdml" const val TYPE = "geometry.spatial.jsRoot"
} }
} }
//TODO add Zelenyy GDML builder here fun DisplayGroup.jsRoot(meta: Meta = EmptyMeta, action: JSRootObject.() -> Unit = {}) =
fun DisplayGroup.gdml(meta: Meta = EmptyMeta, action: GDMLObject.() -> Unit = {}) = JSRootObject(this, meta).apply(action).also { addChild(it) }
GDMLObject(this, meta).apply(action).also { addChild(it) }
fun Meta.toDynamic(): dynamic { fun Meta.toDynamic(): dynamic {
fun MetaItem<*>.toDynamic(): dynamic = when (this) { fun MetaItem<*>.toDynamic(): dynamic = when (this) {
@ -78,19 +76,9 @@ fun Meta.toDynamic(): dynamic {
} }
object ThreeGDMLBuilder : GenericThreeBuilder<GDMLObject, Mesh>() { object ThreeJSRootFactory : MeshThreeFactory<JSRootObject>(JSRootObject::class) {
override fun build(obj: GDMLObject): Mesh { override fun buildGeometry(obj: JSRootObject): BufferGeometry {
val shapeMeta = obj.shape?.toDynamic() ?: error("The shape not defined") val shapeMeta = obj.shape?.toDynamic() ?: error("The shape not defined")
println(shapeMeta) return createGeometry(shapeMeta, obj.facesLimit)
val geometry = createGeometry(shapeMeta, obj.facesLimit)
return Mesh(geometry, obj.color.material()).also { mesh ->
mesh.add(LineSegments(EdgesGeometry(geometry), Materials.DEFAULT))
}
}
override fun update(obj: GDMLObject, target: Mesh) {
val shapeMeta: dynamic = obj.shape?.toDynamic()
target.geometry = createGeometry(shapeMeta, obj.facesLimit)
target.material = obj.color.material()
} }
} }

View File

@ -0,0 +1,25 @@
package hep.dataforge.vis.spatial.jsroot
import hep.dataforge.context.AbstractPlugin
import hep.dataforge.context.Context
import hep.dataforge.context.PluginFactory
import hep.dataforge.context.PluginTag
import hep.dataforge.names.toName
import hep.dataforge.vis.spatial.ThreePlugin
class JSRootPlugin : AbstractPlugin() {
override val tag: PluginTag get() = JSRootPlugin.tag
override fun dependsOn() = listOf(ThreePlugin)
override fun attach(context: Context) {
super.attach(context)
context.plugins.get<ThreePlugin>()?.factories?.set("ThreeJSRootFactory".toName(), ThreeJSRootFactory)
}
companion object: PluginFactory<JSRootPlugin> {
override val tag = PluginTag("vis.jsroot", "hep.dataforge")
override val type = JSRootPlugin::class
override fun build() = JSRootPlugin()
}
}

View File

@ -15,7 +15,7 @@ class Box(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, meta)
//TODO add helper for color configuration //TODO add helper for color configuration
companion object { companion object {
const val TYPE = "geometry.spatial.box" const val TYPE = "geometry.3d.box"
} }
} }

View File

@ -11,7 +11,7 @@ class Convex(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, met
val points = points(properties["points"] ?: error("Vertices not defined")) val points = points(properties["points"] ?: error("Vertices not defined"))
companion object { companion object {
const val TYPE = "geometry.spatial.convex" const val TYPE = "geometry.3d.convex"
fun points(item: MetaItem<*>): List<Point3D> { fun points(item: MetaItem<*>): List<Point3D> {
return item.node?.getAll("point".toName())?.map { (_, value) -> return item.node?.getAll("point".toName())?.map { (_, value) ->

View File

@ -11,7 +11,7 @@ class Extruded(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, TYPE, m
val shape get() = shape(properties["shape"] ?: error("Shape not defined")) val shape get() = shape(properties["shape"] ?: error("Shape not defined"))
companion object { companion object {
const val TYPE = "geometry.spatial.extruded" const val TYPE = "geometry.3d.extruded"
fun shape(item: MetaItem<*>): Shape2D { fun shape(item: MetaItem<*>): Shape2D {
return item.node?.getAll("xyPoint".toName())?.map { (_, value) -> return item.node?.getAll("xyPoint".toName())?.map { (_, value) ->

View File

@ -1,7 +1,7 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.io.Output
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.output.Output
import hep.dataforge.vis.DisplayGroup import hep.dataforge.vis.DisplayGroup
import hep.dataforge.vis.DisplayNode import hep.dataforge.vis.DisplayNode
import hep.dataforge.vis.DisplayObject import hep.dataforge.vis.DisplayObject