Separate modules for jsroot and gdml

This commit is contained in:
Alexander Nozik 2019-07-08 22:11:15 +03:00
parent 67def6cdb5
commit f4221d66cc
47 changed files with 631 additions and 548 deletions

View File

@ -1,5 +1,10 @@
package hep.dataforge.vis.common
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder
import hep.dataforge.meta.buildMeta
import hep.dataforge.meta.set
/**
* Taken from https://github.com/markaren/three.kt/blob/master/threejs-wrapper/src/main/kotlin/info/laht/threekt/math/ColorConstants.kt
*/
@ -175,3 +180,22 @@ object Colors {
const val yellow = 0xFFFF00
const val yellowgreen = 0x9ACD32
}
fun VisualObject.color(rgb: Int) {
this.properties["material"] = rgb
}
fun VisualObject.color(meta: Meta) {
this.properties["material"] = meta
}
fun VisualObject.color(builder: MetaBuilder.() -> Unit) {
color(buildMeta(builder))
}
fun VisualObject.color(r: Int, g: Int, b: Int) = color {
"red" to r
"green" to g
"blue" to b
}

View File

@ -10,33 +10,33 @@ import hep.dataforge.provider.Provider
/**
* A display group which allows both named and unnamed children
*/
class DisplayGroup(
override val parent: DisplayObject? = null, meta: Meta = EmptyMeta
) : DisplayObject, Iterable<DisplayObject>, Provider {
class VisualGroup(
override val parent: VisualObject? = null, meta: Meta = EmptyMeta
) : VisualObject, Iterable<VisualObject>, Provider {
private val namedChildren = HashMap<Name, DisplayObject>()
private val unnamedChildren = ArrayList<DisplayObject>()
private val namedChildren = HashMap<Name, VisualObject>()
private val unnamedChildren = ArrayList<VisualObject>()
override val defaultTarget: String get() = DisplayObject.TYPE
override val defaultTarget: String get() = VisualObject.TYPE
override val properties: Styled = Styled(meta)
override fun iterator(): Iterator<DisplayObject> = (namedChildren.values + unnamedChildren).iterator()
override fun iterator(): Iterator<VisualObject> = (namedChildren.values + unnamedChildren).iterator()
override fun provideTop(target: String): Map<Name, Any> {
return when(target){
DisplayObject.TYPE -> namedChildren
VisualObject.TYPE -> namedChildren
else -> emptyMap()
}
}
private data class Listener(val owner: Any?, val callback: (Name?, DisplayObject?) -> Unit)
private data class Listener(val owner: Any?, val callback: (Name?, VisualObject?) -> Unit)
private val listeners = HashSet<Listener>()
/**
* Add listener for children change
*/
fun onChildrenChange(owner: Any?, action: (Name?, DisplayObject?) -> Unit) {
fun onChildrenChange(owner: Any?, action: (Name?, VisualObject?) -> Unit) {
listeners.add(Listener(owner, action))
}
@ -51,7 +51,7 @@ class DisplayGroup(
/**
*
*/
operator fun set(key: String?, child: DisplayObject?) {
operator fun set(key: String?, child: VisualObject?) {
if(key == null){
} else {
@ -68,7 +68,7 @@ class DisplayGroup(
/**
* Append unnamed child
*/
fun add(child: DisplayObject) {
fun add(child: VisualObject) {
unnamedChildren.add(child)
listeners.forEach { it.callback(null, child) }
}
@ -76,7 +76,7 @@ class DisplayGroup(
/**
* remove unnamed child
*/
fun remove(child: DisplayObject) {
fun remove(child: VisualObject) {
unnamedChildren.remove(child)
listeners.forEach { it.callback(null, null) }
}

View File

@ -4,20 +4,20 @@ import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.provider.Type
import hep.dataforge.vis.common.DisplayObject.Companion.META_KEY
import hep.dataforge.vis.common.DisplayObject.Companion.TAGS_KEY
import hep.dataforge.vis.common.DisplayObject.Companion.TYPE
import hep.dataforge.vis.common.VisualObject.Companion.META_KEY
import hep.dataforge.vis.common.VisualObject.Companion.TAGS_KEY
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
/**
* A root type for display hierarchy
*/
@Type(TYPE)
interface DisplayObject : MetaRepr {
interface VisualObject : MetaRepr {
/**
* The parent object of this one. If null, this one is a root.
*/
val parent: DisplayObject?
val parent: VisualObject?
val properties: Styled
@ -26,7 +26,7 @@ interface DisplayObject : MetaRepr {
}
companion object {
const val TYPE = "display"
const val TYPE = "visual"
const val DEFAULT_TYPE = ""
//const val TYPE_KEY = "@type"
@ -39,14 +39,14 @@ interface DisplayObject : MetaRepr {
/**
* Get the property of this display object of parent's if not found
*/
tailrec fun DisplayObject.getProperty(name: Name): MetaItem<*>? = properties[name] ?: parent?.getProperty(name)
tailrec fun VisualObject.getProperty(name: Name): MetaItem<*>? = properties[name] ?: parent?.getProperty(name)
fun DisplayObject.getProperty(name: String): MetaItem<*>? = getProperty(name.toName())
fun VisualObject.getProperty(name: String): MetaItem<*>? = getProperty(name.toName())
/**
* A change listener for [DisplayObject] configuration.
* A change listener for [VisualObject] configuration.
*/
fun DisplayObject.onChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit) {
fun VisualObject.onChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit) {
properties.onChange(owner, action)
parent?.onChange(owner, action)
}
@ -54,7 +54,7 @@ fun DisplayObject.onChange(owner: Any?, action: (Name, before: MetaItem<*>?, aft
/**
* Remove all meta listeners with matching owners
*/
fun DisplayObject.removeChangeListener(owner: Any?) {
fun VisualObject.removeChangeListener(owner: Any?) {
properties.removeListener(owner)
parent?.removeChangeListener(owner)
}
@ -63,24 +63,24 @@ fun DisplayObject.removeChangeListener(owner: Any?) {
/**
* Additional meta not relevant to display
*/
val DisplayObject.meta: Meta get() = properties[META_KEY]?.node ?: EmptyMeta
val VisualObject.meta: Meta get() = properties[META_KEY]?.node ?: EmptyMeta
val DisplayObject.tags: List<String> get() = properties[TAGS_KEY].stringList
val VisualObject.tags: List<String> get() = properties[TAGS_KEY].stringList
/**
* Basic [DisplayObject] leaf element
* Basic [VisualObject] leaf element
*/
open class DisplayLeaf(
override val parent: DisplayObject?,
override val parent: VisualObject?,
meta: Meta = EmptyMeta
) : DisplayObject {
) : VisualObject {
final override val properties = Styled(meta)
}
///**
// * A group that could contain both named and unnamed children. Unnamed children could be accessed only via
// */
//interface DisplayGroup : DisplayObject, Iterable<DisplayObject>, Provider {
//interface VisualGroup : DisplayObject, Iterable<DisplayObject>, Provider {
// override val defaultTarget: String get() = DisplayObject.TARGET
//
// val children

View File

@ -16,8 +16,8 @@ class DisplayObjectDelegate(
val key: Name?,
val default: MetaItem<*>?,
val inherited: Boolean
) : ReadWriteProperty<DisplayObject, MetaItem<*>?> {
override fun getValue(thisRef: DisplayObject, property: KProperty<*>): MetaItem<*>? {
) : ReadWriteProperty<VisualObject, MetaItem<*>?> {
override fun getValue(thisRef: VisualObject, property: KProperty<*>): MetaItem<*>? {
val name = key ?: property.name.toName()
return if (inherited) {
thisRef.getProperty(name)
@ -26,7 +26,7 @@ class DisplayObjectDelegate(
} ?: default
}
override fun setValue(thisRef: DisplayObject, property: KProperty<*>, value: MetaItem<*>?) {
override fun setValue(thisRef: VisualObject, property: KProperty<*>, value: MetaItem<*>?) {
val name = key ?: property.name.toName()
thisRef.properties[name] = value
}
@ -38,8 +38,8 @@ class DisplayObjectDelegateWrapper<T>(
val inherited: Boolean,
val write: Config.(name: Name, value: T) -> Unit = { name, value -> set(name, value) },
val read: (MetaItem<*>?) -> T?
) : ReadWriteProperty<DisplayObject, T> {
override fun getValue(thisRef: DisplayObject, property: KProperty<*>): T {
) : ReadWriteProperty<VisualObject, T> {
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
val name = key ?: property.name.toName()
return if (inherited) {
read(thisRef.getProperty(name))
@ -48,74 +48,74 @@ class DisplayObjectDelegateWrapper<T>(
} ?: default
}
override fun setValue(thisRef: DisplayObject, property: KProperty<*>, value: T) {
override fun setValue(thisRef: VisualObject, property: KProperty<*>, value: T) {
val name = key ?: property.name.toName()
thisRef.properties[name] = value
}
}
fun DisplayObject.value(default: Value? = null, key: String? = null, inherited: Boolean = true) =
fun VisualObject.value(default: Value? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.value }
fun DisplayObject.string(default: String? = null, key: String? = null, inherited: Boolean = true) =
fun VisualObject.string(default: String? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.string }
fun DisplayObject.boolean(default: Boolean? = null, key: String? = null, inherited: Boolean = true) =
fun VisualObject.boolean(default: Boolean? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.boolean }
fun DisplayObject.number(default: Number? = null, key: String? = null, inherited: Boolean = true) =
fun VisualObject.number(default: Number? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.number }
fun DisplayObject.double(default: Double? = null, key: String? = null, inherited: Boolean = true) =
fun VisualObject.double(default: Double? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
fun DisplayObject.int(default: Int? = null, key: String? = null, inherited: Boolean = true) =
fun VisualObject.int(default: Int? = null, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.int }
fun DisplayObject.node(key: String? = null, inherited: Boolean = true) =
fun VisualObject.node(key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it.node }
fun DisplayObject.item(key: String? = null, inherited: Boolean = true) =
fun VisualObject.item(key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it }
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
@JvmName("safeString")
fun DisplayObject.string(default: String, key: String? = null, inherited: Boolean = true) =
fun VisualObject.string(default: String, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.string }
@JvmName("safeBoolean")
fun DisplayObject.boolean(default: Boolean, key: String? = null, inherited: Boolean = true) =
fun VisualObject.boolean(default: Boolean, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.boolean }
@JvmName("safeNumber")
fun DisplayObject.number(default: Number, key: String? = null, inherited: Boolean = true) =
fun VisualObject.number(default: Number, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.number }
@JvmName("safeDouble")
fun DisplayObject.double(default: Double, key: String? = null, inherited: Boolean = true) =
fun VisualObject.double(default: Double, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
@JvmName("safeInt")
fun DisplayObject.int(default: Int, key: String? = null, inherited: Boolean = true) =
fun VisualObject.int(default: Int, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.int }
inline fun <reified E : Enum<E>> DisplayObject.enum(default: E, key: String? = null, inherited: Boolean = true) =
inline fun <reified E : Enum<E>> VisualObject.enum(default: E, key: String? = null, inherited: Boolean = true) =
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
//merge properties
fun <T> DisplayObject.merge(
fun <T> VisualObject.merge(
key: String? = null,
transformer: (Sequence<MetaItem<*>>) -> T
): ReadOnlyProperty<DisplayObject, T> {
return object : ReadOnlyProperty<DisplayObject, T> {
override fun getValue(thisRef: DisplayObject, property: KProperty<*>): T {
): ReadOnlyProperty<VisualObject, T> {
return object : ReadOnlyProperty<VisualObject, T> {
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
val name = key?.toName() ?: property.name.toName()
val sequence = sequence<MetaItem<*>> {
var thisObj: DisplayObject? = thisRef
var thisObj: VisualObject? = thisRef
while (thisObj != null) {
thisObj.properties[name]?.let { yield(it) }
thisObj = thisObj.parent

View File

@ -0,0 +1,61 @@
import org.jetbrains.kotlin.gradle.frontend.KotlinFrontendExtension
import org.jetbrains.kotlin.gradle.frontend.npm.NpmExtension
import org.jetbrains.kotlin.gradle.frontend.webpack.WebPackExtension
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
plugins {
id("kotlin2js")
id("kotlin-dce-js")
id("org.jetbrains.kotlin.frontend")
}
val kotlinVersion: String by rootProject.extra
dependencies {
implementation(project(":dataforge-vis-spatial-js"))
implementation("info.laht.threekt:threejs-wrapper:0.106-npm-2")
testCompile(kotlin("test-js"))
}
configure<KotlinFrontendExtension> {
downloadNodeJsVersion = "latest"
configure<NpmExtension> {
dependency("three","0.106.2")
devDependency("karma")
}
sourceMaps = true
bundle<WebPackExtension>("webpack") {
this as WebPackExtension
bundleName = "main"
contentPath = file("src/main/web")
sourceMapEnabled = true
//mode = "production"
mode = "development"
}
}
tasks {
"compileKotlin2Js"(Kotlin2JsCompile::class) {
kotlinOptions {
metaInfo = true
outputFile = "${project.buildDir.path}/js/${project.name}.js"
sourceMap = true
moduleKind = "commonjs"
main = "call"
kotlinOptions.sourceMapEmbedSources = "always"
}
}
"compileTestKotlin2Js"(Kotlin2JsCompile::class) {
kotlinOptions {
metaInfo = true
outputFile = "${project.buildDir.path}/js/${project.name}-test.js"
sourceMap = true
moduleKind = "commonjs"
kotlinOptions.sourceMapEmbedSources = "always"
}
}
}

View File

@ -0,0 +1,19 @@
package hep.dataforge.vis.spatial.demo
external val module: Module
external interface Module {
val hot: Hot?
}
external interface Hot {
val data: dynamic
fun accept()
fun accept(dependency: String, callback: () -> Unit)
fun accept(dependencies: Array<String>, callback: (updated: Array<String>) -> Unit)
fun dispose(callback: (data: dynamic) -> Unit)
}
external fun require(name: String): dynamic

View File

@ -8,7 +8,7 @@ import hep.dataforge.vis.common.*
import hep.dataforge.vis.spatial.three.MeshThreeFactory
import info.laht.threekt.core.BufferGeometry
class JSRootGeometry(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) {
class JSRootGeometry(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
var shape by node()
@ -53,7 +53,7 @@ class JSRootGeometry(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, m
}
}
fun DisplayGroup.jsRootGeometry(meta: Meta = EmptyMeta, action: JSRootGeometry.() -> Unit = {}) =
fun VisualGroup.jsRootGeometry(meta: Meta = EmptyMeta, action: JSRootGeometry.() -> Unit = {}) =
JSRootGeometry(this, meta).apply(action).also { add(it) }
//fun Meta.toDynamic(): dynamic {

View File

@ -3,14 +3,14 @@ package hep.dataforge.vis.spatial.jsroot
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.meta.toDynamic
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.DisplayLeaf
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.node
import hep.dataforge.vis.spatial.three.ThreeFactory
import info.laht.threekt.core.Object3D
class JSRootObject(parent: DisplayObject?, meta: Meta, val data: dynamic) : DisplayLeaf(parent, meta) {
class JSRootObject(parent: VisualObject?, meta: Meta, val data: dynamic) : DisplayLeaf(parent, meta) {
var options by node()
@ -28,7 +28,7 @@ object ThreeJSRootObjectFactory : ThreeFactory<JSRootObject> {
}
}
fun DisplayGroup.jsRootObject(str: String) {
fun VisualGroup.jsRootObject(str: String) {
val json = JSON.parse<Any>(str)
JSRootObject(this, EmptyMeta, json).also { add(it) }
}

View File

@ -0,0 +1,49 @@
package hep.dataforge.vis.spatial.demo
import hep.dataforge.vis.spatial.jsroot.JSRootDemoApp
import kotlin.browser.document
import kotlin.dom.hasClass
abstract class ApplicationBase {
abstract val stateKeys: List<String>
abstract fun start(state: Map<String, Any>)
abstract fun dispose(): Map<String, Any>
}
fun main() {
var application: ApplicationBase? = null
val state: dynamic = module.hot?.let { hot ->
hot.accept()
hot.dispose { data ->
data.appState = application?.dispose()
application = null
}
hot.data
}
if (document.body != null) {
application = start(state)
} else {
application = null
document.addEventListener("DOMContentLoaded", { application = start(state) })
}
}
fun start(state: dynamic): ApplicationBase? {
return if (document.body?.hasClass("testApp") == true) {
val application = JSRootDemoApp()
@Suppress("UnsafeCastFromDynamic")
application.start(state?.appState ?: emptyMap<String, Any>())
application
} else {
null
}
}

View File

@ -1,6 +1,6 @@
import * as JSROOT from "JSRootUtils"
import * as JSROOT from "src/main/resources/JSRootUtils"
import * as THREE from "three"
import * as ThreeBSP from "ThreeCSG"
import * as ThreeBSP from "src/main/resources/ThreeCSG"
// Holder of all TGeo-related functions and classes
const GradPerSegm = 6; // grad per segment in cylinder/spherical symmetry shapes

View File

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Three js demo for particle physics</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script type="text/javascript" src="main.bundle.js"></script>
</head>
<body class="testApp">
<div class="container" id="drop_zone" data-toggle="tooltip" data-placement="right"
title="Для загрузки данных в текстовом формате, надо перетащить файл сюда">
Загрузить данные
<br/>
(перетащить файл сюда)
</div>
<div class="container">
<h1>Demo grid</h1>
</div>
<div class="container" id="canvas"></div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
crossorigin="anonymous"></script>
</body>
</html>

View File

@ -3,16 +3,16 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.*
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.getProperty
import hep.dataforge.vis.common.onChange
import javafx.beans.binding.ObjectBinding
import tornadofx.*
/**
* A caching binding collection for [DisplayObject] properties
* A caching binding collection for [VisualObject] properties
*/
class DisplayObjectFXListener(val obj: DisplayObject) {
class DisplayObjectFXListener(val obj: VisualObject) {
private val binndings = HashMap<Name, ObjectBinding<MetaItem<*>?>>()
init {

View File

@ -3,8 +3,8 @@ package hep.dataforge.vis.spatial
import hep.dataforge.context.Context
import hep.dataforge.meta.Meta
import hep.dataforge.output.Output
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import javafx.scene.Group
import javafx.scene.Node
import org.fxyz3d.shapes.primitives.CuboidMesh
@ -14,11 +14,11 @@ import tornadofx.*
* https://github.com/miho/JCSG for operations
*
*/
class FX3DOutput(override val context: Context) : Output<DisplayObject> {
class FX3DOutput(override val context: Context) : Output<VisualObject> {
val canvas by lazy { Canvas3D() }
private fun buildNode(obj: DisplayObject): Node? {
private fun buildNode(obj: VisualObject): Node? {
val listener = DisplayObjectFXListener(obj)
val x = listener["pos.x"].float()
val y = listener["pos.y"].float()
@ -27,7 +27,7 @@ class FX3DOutput(override val context: Context) : Output<DisplayObject> {
org.fxyz3d.geometry.Point3D(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f)
}
return when (obj) {
is DisplayGroup -> Group(obj.map { buildNode(it) }).apply {
is VisualGroup -> Group(obj.map { buildNode(it) }).apply {
this.translateXProperty().bind(x)
this.translateYProperty().bind(y)
this.translateZProperty().bind(z)
@ -43,7 +43,7 @@ class FX3DOutput(override val context: Context) : Output<DisplayObject> {
}
}
override fun render(obj: DisplayObject, meta: Meta) {
override fun render(obj: VisualObject, meta: Meta) {
buildNode(obj)?.let { canvas.world.children.add(it) }
}
}

View File

@ -2,7 +2,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.context.Global
import hep.dataforge.meta.number
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import javafx.scene.Parent
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
@ -21,7 +21,7 @@ class RendererDemoView : View() {
center = renderer.canvas.root
}
lateinit var group: DisplayGroup
lateinit var group: VisualGroup
init {

View File

@ -0,0 +1,18 @@
plugins {
id("scientifik.mpp")
}
repositories{
maven("https://dl.bintray.com/pdvrieze/maven")
}
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api(project(":dataforge-vis-spatial"))
api("scientifik:gdml:0.1.1")
}
}
}
}

View File

@ -0,0 +1,31 @@
//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.meta.Meta
//import hep.dataforge.names.Name
//import hep.dataforge.names.toName
//import hep.dataforge.vis.spatial.three.ThreeFactory
//import hep.dataforge.vis.spatial.three.ThreePlugin
//import kotlin.reflect.KClass
//
//class GDMLPlugin : AbstractPlugin() {
// override val tag: PluginTag get() = GDMLPlugin.tag
//
// override fun dependsOn() = listOf(ThreePlugin)
//
// override fun provideTop(target: String): Map<Name, Any> {
// return when(target){
// ThreeFactory.TYPE-> mapOf("gdml".toName() to ThreeGDMLFactory)
// else -> emptyMap()
// }
// }
//
// companion object : PluginFactory<GDMLPlugin> {
// override val tag = PluginTag("vis.gdml", "hep.dataforge")
// override val type: KClass<GDMLPlugin> = GDMLPlugin::class
// override fun invoke(meta: Meta) = GDMLPlugin()
// }
//}

View File

@ -0,0 +1,92 @@
//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.common.DisplayLeaf
//import hep.dataforge.vis.common.VisualObject
//import hep.dataforge.vis.common.int
//import hep.dataforge.vis.spatial.three.MeshThreeFactory
////import hep.dataforge.vis.spatial.jsroot.createCubeBuffer
////import hep.dataforge.vis.spatial.jsroot.createGeometry
////import hep.dataforge.vis.spatial.jsroot.createTubeBuffer
////import hep.dataforge.vis.spatial.jsroot.createXtruBuffer
//import info.laht.threekt.core.BufferGeometry
//
//
//class GDMLShape(parent: VisualObject?, meta: Meta, val shape: GDMLSolid) :
// DisplayLeaf(parent, 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 -> createCubeBuffer(
// obj.shape.config.toJsRoot()?.toDynamic(),
// obj.facesLimit
// )
// is GDMLTube -> createTubeBuffer(
// obj.shape.config.toJsRoot()?.toDynamic(),
// obj.facesLimit
// )
// is GDMLXtru -> {
// val meta = buildMeta {
// val vertices = obj.shape.vertices
// val zs = obj.shape.sections.sortedBy { it.zOrder!! }
// "fNz" to zs.size
// "fNvert" to vertices.size
// "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 }
// }
// createXtruBuffer(meta.toDynamic(), obj.facesLimit)
// }
// is GDMLUnion -> {
// val meta = buildMeta {
// "fNode.fLeft" to obj.shape.first()?.config.toJsRoot()
// "fNode.fRight" to obj.shape.second()?.config.toJsRoot()
// "fNode._typename" to "TGeoUnion"
// }
// createGeometry(meta.toDynamic(), obj.facesLimit)
// }
// is GDMLSubtraction -> {
// val meta = buildMeta {
// "fNode.fLeft" to obj.shape.first()?.config.toJsRoot()
// "fNode.fRight" to obj.shape.second()?.config.toJsRoot()
// "fNode._typename" to "TGeoSubtraction"
// }
// createGeometry(meta.toDynamic(), obj.facesLimit)
// }
// is GDMLIntersection -> {
// val meta = buildMeta {
// "fNode.fLeft" to obj.shape.first()?.config.toJsRoot()
// "fNode.fRight" to obj.shape.second()?.config.toJsRoot()
// "fNode._typename" to "TGeoIntersection"
// }
// createGeometry(meta.toDynamic(), obj.facesLimit)
// }
//
//
// }
// }
//}

View File

@ -0,0 +1,103 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.color
import hep.dataforge.vis.spatial.*
import scientifik.gdml.*
private fun VisualObject.applyPosition(pos: GDMLPosition): VisualObject = apply {
x = pos.x
y = pos.y
z = pos.z
//TODO convert units if needed
}
private fun VisualObject.applyRotation(rotation: GDMLRotation): VisualObject = apply {
rotationX = rotation.x
rotationY = rotation.y
rotationZ = rotation.z
//TODO convert units if needed
}
private fun VisualGroup.addSolid(root: GDML, solid: GDMLSolid, block: VisualObject.() -> Unit = {}): VisualObject {
return when (solid) {
is GDMLBox -> box(solid.x, solid.y, solid.z)
is GDMLTube -> TODO()
is GDMLXtru -> extrude {
TODO()
}
is GDMLScaledSolid -> {
//Add solid with modified scale
val innerSolid = solid.solidref.resolve(root)
?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined")
addSolid(root, innerSolid) {
block()
scaleX = scaleX.toDouble() * solid.scale.value.toDouble()
scaleY = scaleY.toDouble() * solid.scale.value.toDouble()
scaleZ = scaleZ.toDouble() * solid.scale.value.toDouble()
}
}
is GDMLSphere -> sphere(solid.rmax, solid.deltaphi, solid.deltatheta) {
phiStart = solid.startphi.toDouble()
thetaStart = solid.starttheta.toDouble()
}
is GDMLOrb -> sphere(solid.r)
is GDMLPolyhedra -> TODO()
is GDMLBoolSolid -> {
val first = solid.first.resolve(root) ?: error("")
val second = solid.second.resolve(root) ?: error("")
val type: CompositeType = when (solid) {
is GDMLUnion -> CompositeType.UNION
is GDMLSubtraction -> CompositeType.SUBTRACT
is GDMLIntersection -> CompositeType.INTERSECT
}
return composite(type) {
addSolid(root, first) {
solid.resolveFirstPosition(root)?.let { applyPosition(it) }
solid.resolveFirstRotation(root)?.let { applyRotation(it) }
}
addSolid(root, second) {}
solid.resolvePosition(root)?.let { applyPosition(it) }
solid.resolveRotation(root)?.let { applyRotation(it) }
}
}
}.apply(block)
}
private fun VisualGroup.addVolume(
root: GDML,
gdmlVolume: GDMLVolume,
resolveColor: GDMLMaterialBase.() -> Meta
): VisualGroup {
val solid =
gdmlVolume.solidref.resolve(root)
?: error("Solid with tag ${gdmlVolume.solidref.ref} for volume ${gdmlVolume.name} not defined")
val material =
gdmlVolume.materialref.resolve(root)
?: error("Material with tag ${gdmlVolume.materialref.ref} for volume ${gdmlVolume.name} not defined")
addSolid(root, solid) {
color(material.resolveColor())
}
gdmlVolume.physVolumes.forEach {
val volume = it.volumeref.resolve(root)?: error("Volume with ref ${it.volumeref.ref} could not be resolved")
addVolume(root,volume,resolveColor).apply {
it.resolvePosition(root)?.let { pos -> applyPosition(pos) }
it.resolveRotation(root)?.let { rot -> applyRotation(rot) }
}
}
return this
}
fun GDML.toVisual(): VisualGroup {
//TODO add materials cache
fun GDMLMaterialBase.color(): Meta = EmptyMeta
return VisualGroup().also { it.addVolume(this, world){color()} }
}

View File

@ -4,8 +4,6 @@ import hep.dataforge.context.ContextBuilder
import hep.dataforge.meta.number
import hep.dataforge.vis.common.Colors
import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.jsroot.JSRootPlugin
import hep.dataforge.vis.spatial.jsroot.jsRootGeometry
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
@ -21,12 +19,9 @@ class ThreeDemoApp : ApplicationBase() {
override val stateKeys: List<String> = emptyList()
override fun start(state: Map<String, Any>) {
require("JSRootGeoBase.js")
//TODO replace by optimized builder after dataforge 0.1.3-dev-8
val context = ContextBuilder("three-demo").apply {
plugin(JSRootPlugin())
}.build()
val context = ContextBuilder("three-demo").build()
context.plugins.load(ThreeDemoGrid()).run {
demo("shapes", "Basic shapes") {
@ -76,15 +71,15 @@ class ThreeDemoApp : ApplicationBase() {
}
}
demo("jsroot", "JSROOT cube") {
jsRootGeometry {
y = 110.0
shape = box(50, 50, 50)
color(Colors.lightcoral)
rotationX = PI / 4
rotationY = PI / 4
}
}
// demo("jsroot", "JSROOT cube") {
// jsRootGeometry {
// y = 110.0
// shape = box(50, 50, 50)
// color(Colors.lightcoral)
// rotationX = PI / 4
// rotationY = PI / 4
// }
// }
demo("extrude", "extruded shape") {
extrude {

View File

@ -12,8 +12,8 @@ import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.output.Output
import hep.dataforge.output.OutputManager
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.render
import hep.dataforge.vis.spatial.three.ThreeOutput
import hep.dataforge.vis.spatial.three.ThreePlugin
@ -49,7 +49,7 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
val three = context.plugins.get<ThreePlugin>()!!
return outputs.getOrPut(name) {
if (type != DisplayObject::class) error("Supports only DisplayObject")
if (type != VisualObject::class) error("Supports only DisplayObject")
val output = three.output(meta) {
"axis" to {
"size" to 500
@ -79,10 +79,10 @@ class ThreeDemoGrid(meta: Meta) : AbstractPlugin(meta), OutputManager {
}
}
fun ThreeDemoGrid.demo(name: String, title: String = name, block: DisplayGroup.() -> Unit) {
fun ThreeDemoGrid.demo(name: String, title: String = name, block: VisualGroup.() -> Unit) {
val meta = buildMeta {
"title" to title
}
val output = get<DisplayObject>(DisplayObject::class, name.toName(), meta = meta)
val output = get<VisualObject>(VisualObject::class, name.toName(), meta = meta)
output.render(action = block)
}

View File

@ -1,54 +0,0 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.Config
@DslMarker
annotation class GDMLApi
@GDMLApi
class GDML {
private val defines = GDMLDefineContainer()
private var solids = GDMLSolidContainer()
fun define(block: GDMLDefineContainer.() -> Unit) {
defines.apply(block).map
}
fun solids(block: GDMLSolidContainer.() -> Unit) {
solids.apply(block).map
}
fun getPosition(ref: String) = defines.map[ref] as? GDMLPosition
fun getRotation(ref: String) = defines.map[ref] as? GDMLRotation
fun getSolid(ref:String) = solids.map[ref]
}
@GDMLApi
class GDMLDefineContainer {
internal val map = HashMap<String, GDMLDefine>()
fun position(name: String, block: GDMLPosition.() -> Unit) {
map[name] = GDMLPosition(Config()).apply(block).apply { this.pName = name }
}
fun rotation(name: String, block: GDMLRotation.() -> Unit) {
map[name] = GDMLRotation(Config()).apply(block).apply { this.pName = name }
}
}
@GDMLApi
class GDMLSolidContainer {
internal val map = HashMap<String, GDMLSolid>()
operator fun get(ref: String) = map[ref]
fun box(name: String, block: GDMLBox.() -> Unit) {
map[name] = GDMLBox.build(block).apply{this.pName = name}
}
fun tube(name: String, block: GDMLTube.() -> Unit){
map[name] = GDMLTube.build(block).apply{this.pName = name}
}
fun xtru(name: String, block: GDMLXtru.() -> Unit) {
map[name] = GDMLXtru.build(block).apply{this.pName = name}
}
}

View File

@ -1,182 +0,0 @@
package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.*
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
sealed class GDMLNode(override val config: Config) : Specific {
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")
companion object : Specification<GDMLPosition> {
override fun wrap(config: Config) = GDMLPosition(config)
}
}
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")
companion object : Specification<GDMLRotation> {
override fun wrap(config: Config) = GDMLRotation(config)
}
}
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 : Specification<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 : Specification<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) : Specific {
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 : Specification<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 : Specification<GDMLXtru> {
override fun wrap(config: Config): GDMLXtru = GDMLXtru(config)
}
}
internal class GDMLRefDelegate(val key: String?) : ReadWriteProperty<GDMLNode, String?> {
override fun getValue(thisRef: GDMLNode, property: KProperty<*>): String? {
val realKey = key ?: property.name
return thisRef.config["$realKey.ref"].string
}
override fun setValue(thisRef: GDMLNode, property: KProperty<*>, value: String?) {
val realKey = key ?: property.name
if (value == null) {
thisRef.config.remove(realKey)
} else {
thisRef.config["$realKey.ref"] = value
}
}
}
internal fun GDMLNode.ref(key: String? = null) = GDMLRefDelegate(key)
sealed class GDMLBoolSolid(config: Config, var root: GDML? = null) : GDMLSolid(config) {
var first by ref()
@JsName("resolveFirst")
fun first() = first?.let{ref -> root?.getSolid(ref)}
var second by ref()
@JsName("resolveSecond")
fun second() = second?.let{ref -> root?.getSolid(ref)}
var position by spec(GDMLPosition)
var positionref by ref()
/**
* Get the position from either position block or reference (if root is provided)
*/
@JsName("resolvePosition")
fun position() = position ?: positionref?.let{ref -> root?.getPosition(ref)}
var rotation by spec(GDMLRotation)
var rotationref by ref()
/**
* Get the rotation from either position block or reference (if root is provided)
*/
@JsName("resolveRotation")
fun rotation() = rotation ?: rotationref?.let{ref -> root?.getRotation(ref)}
var firstposition by spec(GDMLPosition)
var firstrotation by spec(GDMLRotation)
}
class GDMLUnion(config: Config) : GDMLBoolSolid(config) {
override val type: String = "union"
companion object : Specification<GDMLUnion> {
override fun wrap(config: Config): GDMLUnion = GDMLUnion(config)
}
}
class GDMLSubtraction(config: Config) : GDMLBoolSolid(config) {
override val type: String = "subtraction"
companion object : Specification<GDMLUnion> {
override fun wrap(config: Config) = GDMLUnion(config)
}
}
class GDMLIntersection(config: Config) : GDMLBoolSolid(config) {
override val type: String = "intersection"
companion object : Specification<GDMLIntersection> {
override fun wrap(config: Config) = GDMLIntersection(config)
}
}

View File

@ -1,31 +0,0 @@
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.meta.Meta
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.vis.spatial.three.ThreeFactory
import hep.dataforge.vis.spatial.three.ThreePlugin
import kotlin.reflect.KClass
class GDMLPlugin : AbstractPlugin() {
override val tag: PluginTag get() = GDMLPlugin.tag
override fun dependsOn() = listOf(ThreePlugin)
override fun provideTop(target: String): Map<Name, Any> {
return when(target){
ThreeFactory.TYPE-> mapOf("gdml".toName() to ThreeGDMLFactory)
else -> emptyMap()
}
}
companion object : PluginFactory<GDMLPlugin> {
override val tag = PluginTag("vis.gdml", "hep.dataforge")
override val type: KClass<GDMLPlugin> = GDMLPlugin::class
override fun invoke(meta: Meta) = GDMLPlugin()
}
}

View File

@ -1,92 +0,0 @@
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.common.DisplayLeaf
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.int
import hep.dataforge.vis.spatial.three.MeshThreeFactory
import hep.dataforge.vis.spatial.jsroot.createCubeBuffer
import hep.dataforge.vis.spatial.jsroot.createGeometry
import hep.dataforge.vis.spatial.jsroot.createTubeBuffer
import hep.dataforge.vis.spatial.jsroot.createXtruBuffer
import info.laht.threekt.core.BufferGeometry
class GDMLShape(parent: DisplayObject?, meta: Meta, val shape: GDMLSolid) :
DisplayLeaf(parent, 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 -> createCubeBuffer(
obj.shape.config.toJsRoot()?.toDynamic(),
obj.facesLimit
)
is GDMLTube -> createTubeBuffer(
obj.shape.config.toJsRoot()?.toDynamic(),
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
"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 }
}
createXtruBuffer(meta.toDynamic(), obj.facesLimit)
}
is GDMLUnion -> {
val meta = buildMeta {
"fNode.fLeft" to obj.shape.first()?.config.toJsRoot()
"fNode.fRight" to obj.shape.second()?.config.toJsRoot()
"fNode._typename" to "TGeoUnion"
}
createGeometry(meta.toDynamic(), obj.facesLimit)
}
is GDMLSubtraction -> {
val meta = buildMeta {
"fNode.fLeft" to obj.shape.first()?.config.toJsRoot()
"fNode.fRight" to obj.shape.second()?.config.toJsRoot()
"fNode._typename" to "TGeoSubtraction"
}
createGeometry(meta.toDynamic(), obj.facesLimit)
}
is GDMLIntersection -> {
val meta = buildMeta {
"fNode.fLeft" to obj.shape.first()?.config.toJsRoot()
"fNode.fRight" to obj.shape.second()?.config.toJsRoot()
"fNode._typename" to "TGeoIntersection"
}
createGeometry(meta.toDynamic(), obj.facesLimit)
}
}
}
}

View File

@ -4,7 +4,7 @@ import hep.dataforge.meta.boolean
import hep.dataforge.names.startsWith
import hep.dataforge.names.toName
import hep.dataforge.provider.Type
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.getProperty
import hep.dataforge.vis.common.onChange
import hep.dataforge.vis.spatial.*
@ -19,13 +19,13 @@ import info.laht.threekt.objects.LineSegments
import info.laht.threekt.objects.Mesh
import kotlin.reflect.KClass
internal val DisplayObject.material get() = getProperty("material").material()
internal val VisualObject.material get() = getProperty("material").material()
/**
* Builder and updater for three.js object
*/
@Type(TYPE)
interface ThreeFactory<T : DisplayObject> {
interface ThreeFactory<T : VisualObject> {
val type: KClass<out T>
@ -34,7 +34,7 @@ interface ThreeFactory<T : DisplayObject> {
companion object {
const val TYPE = "threeFactory"
fun <T : DisplayObject> buildMesh(obj: T, geometryBuilder: (T) -> BufferGeometry): Mesh {
fun <T : VisualObject> buildMesh(obj: T, geometryBuilder: (T) -> BufferGeometry): Mesh {
val geometry = geometryBuilder(obj)
//JS sometimes tries to pass Geometry as BufferGeometry
@ -84,7 +84,7 @@ interface ThreeFactory<T : DisplayObject> {
/**
* Update position, rotation and visibility
*/
internal fun Object3D.updatePosition(obj: DisplayObject) {
internal fun Object3D.updatePosition(obj: VisualObject) {
position.set(obj.x, obj.y, obj.z)
setRotationFromEuler(obj.euler)
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
@ -94,7 +94,7 @@ internal fun Object3D.updatePosition(obj: DisplayObject) {
/**
* Unsafe invocation of a factory
*/
operator fun <T : DisplayObject> ThreeFactory<T>.invoke(obj: Any): Object3D {
operator fun <T : VisualObject> ThreeFactory<T>.invoke(obj: Any): Object3D {
if (type.isInstance(obj)) {
return invoke(obj as T)
} else {
@ -105,7 +105,7 @@ operator fun <T : DisplayObject> ThreeFactory<T>.invoke(obj: Any): Object3D {
/**
* Basic geometry-based factory
*/
abstract class MeshThreeFactory<T : DisplayObject>(override val type: KClass<out T>) :
abstract class MeshThreeFactory<T : VisualObject>(override val type: KClass<out T>) :
ThreeFactory<T> {
/**
* Build a geometry for an object

View File

@ -4,7 +4,7 @@ import hep.dataforge.context.Context
import hep.dataforge.meta.*
import hep.dataforge.output.Output
import hep.dataforge.vis.common.Colors
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.demo.require
import info.laht.threekt.WebGLRenderer
import info.laht.threekt.helpers.AxesHelper
@ -15,7 +15,7 @@ import kotlin.browser.window
private val elementResizeEvent = require("element-resize-event")
class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Output<DisplayObject> {
class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Output<VisualObject> {
override val context: Context get() = three.context
@ -58,7 +58,7 @@ class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Output<D
animate()
}
override fun render(obj: DisplayObject, meta: Meta) {
override fun render(obj: VisualObject, meta: Meta) {
scene.add(three.buildObject3D(obj))
}
}

View File

@ -5,8 +5,8 @@ import hep.dataforge.context.PluginFactory
import hep.dataforge.context.PluginTag
import hep.dataforge.context.content
import hep.dataforge.meta.*
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.*
import info.laht.threekt.cameras.Camera
import info.laht.threekt.cameras.PerspectiveCamera
@ -20,7 +20,7 @@ import kotlin.reflect.KClass
class ThreePlugin : AbstractPlugin() {
override val tag: PluginTag get() = Companion.tag
private val objectFactories = HashMap<KClass<out DisplayObject>, ThreeFactory<*>>()
private val objectFactories = HashMap<KClass<out VisualObject>, ThreeFactory<*>>()
private val compositeFactory = ThreeCompositeFactory(this)
init {
@ -30,14 +30,14 @@ class ThreePlugin : AbstractPlugin() {
objectFactories[Sphere::class] = ThreeSphereFactory
}
private fun findObjectFactory(type: KClass<out DisplayObject>): ThreeFactory<*>? {
private fun findObjectFactory(type: KClass<out VisualObject>): ThreeFactory<*>? {
return objectFactories[type]
?: context.content<ThreeFactory<*>>(ThreeFactory.TYPE).values.find { it.type == type }
}
fun buildObject3D(obj: DisplayObject): Object3D {
fun buildObject3D(obj: VisualObject): Object3D {
return when (obj) {
is DisplayGroup -> Group(obj.map { buildObject3D(it) }).apply {
is VisualGroup -> Group(obj.map { buildObject3D(it) }).apply {
updatePosition(obj)
}
is Composite -> compositeFactory(obj)

View File

@ -4,7 +4,7 @@ import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.float
import hep.dataforge.meta.get
import hep.dataforge.meta.node
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.spatial.rotationOrder
import hep.dataforge.vis.spatial.rotationX
import hep.dataforge.vis.spatial.rotationY
@ -25,7 +25,7 @@ fun Group(children: Collection<Object3D>) = info.laht.threekt.objects.Group().ap
children.forEach { this.add(it) }
}
val DisplayObject.euler get() = Euler(rotationX, rotationY, rotationZ, rotationOrder.name)
val VisualObject.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)

View File

@ -2,12 +2,12 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.DisplayLeaf
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.double
class Box(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape {
class Box(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape {
var xSize by double(100.0)
var ySize by double(100.0)
var zSize by double(100.0)
@ -36,13 +36,14 @@ class Box(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape
companion object {
const val TYPE = "geometry.3d.box"
}
}
fun DisplayGroup.box(meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
fun VisualGroup.box(meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
Box(this, meta).apply(action).also { add(it) }
fun DisplayGroup.box(xSize: Number, ySize: Number, zSize: Number, meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
fun VisualGroup.box(xSize: Number, ySize: Number, zSize: Number, meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
Box(this, meta).apply(action).apply{
this.xSize = xSize.toDouble()
this.ySize = ySize.toDouble()

View File

@ -3,9 +3,9 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.meta.seal
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.DisplayLeaf
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
enum class CompositeType {
UNION,
@ -14,25 +14,25 @@ enum class CompositeType {
}
class Composite(
parent: DisplayObject?,
val first: DisplayObject,
val second: DisplayObject,
parent: VisualObject?,
val first: VisualObject,
val second: VisualObject,
val type: CompositeType = CompositeType.UNION,
meta: Meta = EmptyMeta
) : DisplayLeaf(parent, meta)
fun DisplayGroup.composite(type: CompositeType, builder: DisplayGroup.() -> Unit): Composite {
val group = DisplayGroup().apply(builder)
fun VisualGroup.composite(type: CompositeType, builder: VisualGroup.() -> Unit): Composite {
val group = VisualGroup().apply(builder)
val children = group.toList()
if (children.size != 2) error("Composite requires exactly two children")
return Composite(this, children[0], children[1], type, group.properties.seal()).also { add(it) }
}
fun DisplayGroup.union(builder: DisplayGroup.() -> Unit) =
fun VisualGroup.union(builder: VisualGroup.() -> Unit) =
composite(CompositeType.UNION,builder)
fun DisplayGroup.subtract(builder: DisplayGroup.() -> Unit) =
fun VisualGroup.subtract(builder: VisualGroup.() -> Unit) =
composite(CompositeType.SUBTRACT,builder)
fun DisplayGroup.intersect(builder: DisplayGroup.() -> Unit) =
fun VisualGroup.intersect(builder: VisualGroup.() -> Unit) =
composite(CompositeType.INTERSECT,builder)

View File

@ -1,11 +1,11 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.*
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.DisplayLeaf
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
class Convex(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) {
class Convex(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
val points = points(properties["points"] ?: error("Vertices not defined"))
@ -20,7 +20,7 @@ class Convex(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) {
}
}
fun DisplayGroup.convex(meta: Meta = EmptyMeta, action: ConvexBuilder.() -> Unit = {}) =
fun VisualGroup.convex(meta: Meta = EmptyMeta, action: ConvexBuilder.() -> Unit = {}) =
ConvexBuilder().apply(action).build(this, meta).also { add(it) }
class ConvexBuilder {
@ -30,7 +30,7 @@ class ConvexBuilder {
points.add(Point3D(x, y, z))
}
fun build(parent: DisplayObject?, meta: Meta): Convex {
fun build(parent: VisualObject?, meta: Meta): Convex {
val points = buildMeta {
points.forEachIndexed { index, value ->
"points.point[$index]" to value.toMeta()

View File

@ -1,9 +1,9 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.*
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.DisplayLeaf
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
@ -42,7 +42,7 @@ class Layer(override val config: Config) : Specific {
//class Layer(val z: Number, val x: Number = 0.0, val y: Number = 0.0, val scale: Number = 1.0)
class Extruded(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape {
class Extruded(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape {
val shape
get() = properties.getAll("shape.point").map { (_, value) ->
@ -119,5 +119,5 @@ class Extruded(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta),
}
}
fun DisplayGroup.extrude(meta: Meta = EmptyMeta, action: Extruded.() -> Unit = {}) =
fun VisualGroup.extrude(meta: Meta = EmptyMeta, action: Extruded.() -> Unit = {}) =
Extruded(this, meta).apply(action).also { add(it) }

View File

@ -1,7 +1,7 @@
package hep.dataforge.vis.spatial
import hep.dataforge.meta.*
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
data class Point2D(val x: Number, val y: Number) : MetaRepr {
override fun toMeta(): Meta = buildMeta {
@ -60,6 +60,6 @@ fun GeometryBuilder<*>.face4(
face(vertex1, vertex3, vertex4, normal, meta)
}
interface Shape : DisplayObject {
interface Shape : VisualObject {
fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>)
}

View File

@ -2,13 +2,13 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.EmptyMeta
import hep.dataforge.meta.Meta
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.DisplayLeaf
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.double
import kotlin.math.PI
class Sphere(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) {
class Sphere(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
var radius by double(50.0)
var phiStart by double(0.0)
var phi by double(2 * PI)
@ -16,10 +16,10 @@ class Sphere(parent: DisplayObject?, meta: Meta) : DisplayLeaf(parent, meta) {
var theta by double(PI)
}
fun DisplayGroup.sphere(meta: Meta = EmptyMeta, action: Sphere.() -> Unit = {}) =
fun VisualGroup.sphere(meta: Meta = EmptyMeta, action: Sphere.() -> Unit = {}) =
Sphere(this, meta).apply(action).also { add(it) }
fun DisplayGroup.sphere(
fun VisualGroup.sphere(
radius: Number,
phi: Number = 2 * PI,
theta: Number = PI,

View File

@ -2,16 +2,16 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.*
import hep.dataforge.output.Output
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.DisplayObject
import hep.dataforge.vis.common.VisualGroup
import hep.dataforge.vis.common.VisualObject
import hep.dataforge.vis.common.getProperty
fun DisplayGroup.group(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit = {}): DisplayGroup =
DisplayGroup(this, meta).apply(action).also { add(it) }
fun VisualGroup.group(meta: Meta = EmptyMeta, action: VisualGroup.() -> Unit = {}): VisualGroup =
VisualGroup(this, meta).apply(action).also { add(it) }
fun Output<DisplayObject>.render(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit) =
render(DisplayGroup(null, EmptyMeta).apply(action), meta)
fun Output<VisualObject>.render(meta: Meta = EmptyMeta, action: VisualGroup.() -> Unit) =
render(VisualGroup(null, EmptyMeta).apply(action), meta)
//TODO replace properties by containers?
@ -20,7 +20,7 @@ fun Output<DisplayObject>.render(meta: Meta = EmptyMeta, action: DisplayGroup.()
/**
* Visibility property. Inherited from parent
*/
var DisplayObject.visible
var VisualObject.visible
get() = getProperty("visible").boolean ?: true
set(value) {
properties["visible"] = value
@ -31,7 +31,7 @@ var DisplayObject.visible
/**
* x position property relative to parent. Not inherited
*/
var DisplayObject.x
var VisualObject.x
get() = properties["pos.x"].number ?: 0.0
set(value) {
properties["pos.x"] = value
@ -40,7 +40,7 @@ var DisplayObject.x
/**
* y position property. Not inherited
*/
var DisplayObject.y
var VisualObject.y
get() = properties["pos.y"].number ?: 0.0
set(value) {
properties["pos.y"] = value
@ -49,7 +49,7 @@ var DisplayObject.y
/**
* z position property. Not inherited
*/
var DisplayObject.z
var VisualObject.z
get() = properties["pos.z"].number ?: 0.0
set(value) {
properties["pos.z"] = value
@ -60,7 +60,7 @@ var DisplayObject.z
/**
* x rotation relative to parent. Not inherited
*/
var DisplayObject.rotationX
var VisualObject.rotationX
get() = properties["rotation.x"].number ?: 0.0
set(value) {
properties["rotation.x"] = value
@ -69,7 +69,7 @@ var DisplayObject.rotationX
/**
* y rotation relative to parent. Not inherited
*/
var DisplayObject.rotationY
var VisualObject.rotationY
get() = properties["rotation.y"].number ?: 0.0
set(value) {
properties["rotation.y"] = value
@ -78,7 +78,7 @@ var DisplayObject.rotationY
/**
* z rotation relative to parent. Not inherited
*/
var DisplayObject.rotationZ
var VisualObject.rotationZ
get() = properties["rotation.z"].number ?: 0.0
set(value) {
properties["rotation.z"] = value
@ -96,7 +96,7 @@ enum class RotationOrder {
/**
* Rotation order. Not inherited
*/
var DisplayObject.rotationOrder: RotationOrder
var VisualObject.rotationOrder: RotationOrder
get() = getProperty("rotation.order").enum<RotationOrder>() ?: RotationOrder.XYZ
set(value) {
properties["rotation.order"] = value
@ -107,7 +107,7 @@ var DisplayObject.rotationOrder: RotationOrder
/**
* X scale. Not inherited
*/
var DisplayObject.scaleX
var VisualObject.scaleX
get() = properties["scale.x"].number ?: 1.0
set(value) {
properties["scale.x"] = value
@ -116,7 +116,7 @@ var DisplayObject.scaleX
/**
* Y scale. Not inherited
*/
var DisplayObject.scaleY
var VisualObject.scaleY
get() = properties["scale.y"].number ?: 1.0
set(value) {
properties["scale.y"] = value
@ -125,36 +125,18 @@ var DisplayObject.scaleY
/**
* Z scale. Not inherited
*/
var DisplayObject.scaleZ
var VisualObject.scaleZ
get() = properties["scale.z"].number ?: 1.0
set(value) {
properties["scale.z"] = value
}
fun DisplayObject.color(rgb: Int) {
this.properties["material"] = rgb
}
fun DisplayObject.color(meta: Meta) {
this.properties["material"] = meta
}
fun DisplayObject.color(builder: MetaBuilder.()->Unit) {
color(buildMeta(builder))
}
fun DisplayObject.color(r: Int, g: Int, b: Int) = color{
"red" to r
"green" to g
"blue" to b
}
//TODO add inherited scale
/**
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default
*/
var DisplayObject.detail: Int?
var VisualObject.detail: Int?
get() = properties["detail"]?.int
set(value) {
properties["detail"] = value

View File

@ -4,14 +4,14 @@ import hep.dataforge.meta.get
import hep.dataforge.meta.getAll
import hep.dataforge.meta.node
import hep.dataforge.names.toName
import hep.dataforge.vis.common.DisplayGroup
import hep.dataforge.vis.common.VisualGroup
import kotlin.test.Test
import kotlin.test.assertEquals
class ConvexTest {
@Test
fun testConvexBuilder() {
val group = DisplayGroup().apply {
val group = VisualGroup().apply {
convex {
point(50, 50, -50)
point(50, -50, -50)

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

18
gradlew vendored
View File

@ -1,5 +1,21 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
@ -28,7 +44,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

18
gradlew.bat vendored
View File

@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

View File

@ -33,7 +33,9 @@ include(
":dataforge-vis-fx",
":dataforge-vis-spatial",
":dataforge-vis-spatial-fx",
":dataforge-vis-spatial-js"
":dataforge-vis-spatial-js",
":dataforge-vis-jsroot",
":dataforge-vis-spatial-gdml"
)
//if(file("../dataforge-core").exists()) {