From f4221d66cce838d2e8d55376e4a00faf717516e7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 8 Jul 2019 22:11:15 +0300 Subject: [PATCH] Separate modules for jsroot and gdml --- .../kotlin/hep/dataforge/vis/common/Colors.kt | 24 +++ .../{DisplayGroup.kt => VisualGroup.kt} | 26 +-- .../{DisplayObject.kt => VisualObject.kt} | 34 ++-- ...tDelegates.kt => VisualObjectDelegates.kt} | 50 ++--- dataforge-vis-jsroot/build.gradle.kts | 61 ++++++ .../kotlin/hep/dataforge/vis/jsroot/HMR.kt | 19 ++ .../hep/dataforge/vis}/jsroot/JSRoot.kt | 0 .../dataforge/vis}/jsroot/JSRootDemoApp.kt | 0 .../hep/dataforge/vis}/jsroot/JSRootGEO.kt | 0 .../dataforge/vis}/jsroot/JSRootGeometry.kt | 4 +- .../hep/dataforge/vis}/jsroot/JSRootObject.kt | 8 +- .../hep/dataforge/vis}/jsroot/JSRootPlugin.kt | 0 .../kotlin/hep/dataforge/vis/jsroot/main.kt | 49 +++++ .../src/main/resources/JSRootGeoBase.js | 4 +- .../src/main/resources/JSRootUtils.js | 0 .../src/main/resources/ThreeCSG.js | 0 dataforge-vis-jsroot/src/main/web/index.html | 33 ++++ .../vis/spatial/DisplayObjectFXListener.kt | 6 +- .../hep/dataforge/vis/spatial/FX3DOutput.kt | 12 +- .../dataforge/vis/spatial/RendererDemoApp.kt | 4 +- dataforge-vis-spatial-gdml/build.gradle.kts | 18 ++ .../dataforge/vis/spatial/gdml/GDMLPlugin.kt | 31 +++ .../vis/spatial/gdml/ThreeGDMLFactory.kt | 92 +++++++++ .../dataforge/vis/spatial/gdml/visualGDML.kt | 103 ++++++++++ .../vis/spatial/demo/ThreeDemoApp.kt | 33 ++-- .../vis/spatial/demo/ThreeDemoGrid.kt | 10 +- .../hep/dataforge/vis/spatial/gdml/GDML.kt | 54 ------ .../dataforge/vis/spatial/gdml/GDMLNodes.kt | 182 ------------------ .../dataforge/vis/spatial/gdml/GDMLPlugin.kt | 31 --- .../vis/spatial/gdml/ThreeGDMLFactory.kt | 92 --------- .../vis/spatial/three/ThreeFactory.kt | 14 +- .../vis/spatial/three/ThreeOutput.kt | 6 +- .../vis/spatial/three/ThreePlugin.kt | 12 +- .../hep/dataforge/vis/spatial/three/three.kt | 4 +- .../kotlin/hep/dataforge/vis/spatial/Box.kt | 11 +- .../hep/dataforge/vis/spatial/Composite.kt | 20 +- .../hep/dataforge/vis/spatial/Convex.kt | 10 +- .../hep/dataforge/vis/spatial/Extruded.kt | 8 +- .../dataforge/vis/spatial/GeometryBuilder.kt | 4 +- .../hep/dataforge/vis/spatial/Sphere.kt | 10 +- .../dataforge/vis/spatial/displayObject3D.kt | 54 ++---- .../hep/dataforge/vis/spatial/ConvexTest.kt | 4 +- gradle/wrapper/gradle-wrapper.jar | Bin 55190 -> 55616 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 18 +- gradlew.bat | 18 +- settings.gradle.kts | 4 +- 47 files changed, 631 insertions(+), 548 deletions(-) rename dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/{DisplayGroup.kt => VisualGroup.kt} (67%) rename dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/{DisplayObject.kt => VisualObject.kt} (56%) rename dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/{DisplayObjectDelegates.kt => VisualObjectDelegates.kt} (61%) create mode 100644 dataforge-vis-jsroot/build.gradle.kts create mode 100644 dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/HMR.kt rename {dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial => dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis}/jsroot/JSRoot.kt (100%) rename {dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial => dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis}/jsroot/JSRootDemoApp.kt (100%) rename {dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial => dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis}/jsroot/JSRootGEO.kt (100%) rename {dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial => dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis}/jsroot/JSRootGeometry.kt (92%) rename {dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial => dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis}/jsroot/JSRootObject.kt (75%) rename {dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial => dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis}/jsroot/JSRootPlugin.kt (100%) create mode 100644 dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/main.kt rename {dataforge-vis-spatial-js => dataforge-vis-jsroot}/src/main/resources/JSRootGeoBase.js (99%) rename {dataforge-vis-spatial-js => dataforge-vis-jsroot}/src/main/resources/JSRootUtils.js (100%) rename {dataforge-vis-spatial-js => dataforge-vis-jsroot}/src/main/resources/ThreeCSG.js (100%) create mode 100644 dataforge-vis-jsroot/src/main/web/index.html create mode 100644 dataforge-vis-spatial-gdml/build.gradle.kts create mode 100644 dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt create mode 100644 dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt create mode 100644 dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt delete mode 100644 dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDML.kt delete mode 100644 dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLNodes.kt delete mode 100644 dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt delete mode 100644 dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Colors.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Colors.kt index 0365e300..340caa59 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Colors.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/Colors.kt @@ -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 */ @@ -174,4 +179,23 @@ object Colors { const val whitesmoke = 0xF5F5F5 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 } \ No newline at end of file diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayGroup.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt similarity index 67% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayGroup.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt index e7330f52..e5cb4b47 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayGroup.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualGroup.kt @@ -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, Provider { +class VisualGroup( + override val parent: VisualObject? = null, meta: Meta = EmptyMeta +) : VisualObject, Iterable, Provider { - private val namedChildren = HashMap() - private val unnamedChildren = ArrayList() + private val namedChildren = HashMap() + private val unnamedChildren = ArrayList() - override val defaultTarget: String get() = DisplayObject.TYPE + override val defaultTarget: String get() = VisualObject.TYPE override val properties: Styled = Styled(meta) - override fun iterator(): Iterator = (namedChildren.values + unnamedChildren).iterator() + override fun iterator(): Iterator = (namedChildren.values + unnamedChildren).iterator() override fun provideTop(target: String): Map { 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() /** * 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) } } diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayObject.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt similarity index 56% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayObject.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt index 5639326b..a15b15b8 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayObject.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObject.kt @@ -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 get() = properties[TAGS_KEY].stringList +val VisualObject.tags: List 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, Provider { +//interface VisualGroup : DisplayObject, Iterable, Provider { // override val defaultTarget: String get() = DisplayObject.TARGET // // val children diff --git a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayObjectDelegates.kt b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObjectDelegates.kt similarity index 61% rename from dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayObjectDelegates.kt rename to dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObjectDelegates.kt index 8dcb9286..8879cbd1 100644 --- a/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/DisplayObjectDelegates.kt +++ b/dataforge-vis-common/src/commonMain/kotlin/hep/dataforge/vis/common/VisualObjectDelegates.kt @@ -16,8 +16,8 @@ class DisplayObjectDelegate( val key: Name?, val default: MetaItem<*>?, val inherited: Boolean -) : ReadWriteProperty?> { - override fun getValue(thisRef: DisplayObject, property: KProperty<*>): MetaItem<*>? { +) : ReadWriteProperty?> { + 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( val inherited: Boolean, val write: Config.(name: Name, value: T) -> Unit = { name, value -> set(name, value) }, val read: (MetaItem<*>?) -> T? -) : ReadWriteProperty { - override fun getValue(thisRef: DisplayObject, property: KProperty<*>): T { +) : ReadWriteProperty { + 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( } ?: 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 Configurable.spec(spec: Specification, key: String? = null) = ChildConfigDelegate(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 > DisplayObject.enum(default: E, key: String? = null, inherited: Boolean = true) = +inline fun > VisualObject.enum(default: E, key: String? = null, inherited: Boolean = true) = DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf(it) } } //merge properties -fun DisplayObject.merge( +fun VisualObject.merge( key: String? = null, transformer: (Sequence>) -> T -): ReadOnlyProperty { - return object : ReadOnlyProperty { - override fun getValue(thisRef: DisplayObject, property: KProperty<*>): T { +): ReadOnlyProperty { + return object : ReadOnlyProperty { + override fun getValue(thisRef: VisualObject, property: KProperty<*>): T { val name = key?.toName() ?: property.name.toName() val sequence = sequence> { - var thisObj: DisplayObject? = thisRef + var thisObj: VisualObject? = thisRef while (thisObj != null) { thisObj.properties[name]?.let { yield(it) } thisObj = thisObj.parent diff --git a/dataforge-vis-jsroot/build.gradle.kts b/dataforge-vis-jsroot/build.gradle.kts new file mode 100644 index 00000000..0129a2cf --- /dev/null +++ b/dataforge-vis-jsroot/build.gradle.kts @@ -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 { + downloadNodeJsVersion = "latest" + + configure { + dependency("three","0.106.2") + devDependency("karma") + } + + sourceMaps = true + + bundle("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" + } + } +} \ No newline at end of file diff --git a/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/HMR.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/HMR.kt new file mode 100644 index 00000000..d5f5fffe --- /dev/null +++ b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/HMR.kt @@ -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, callback: (updated: Array) -> Unit) + + fun dispose(callback: (data: dynamic) -> Unit) +} + +external fun require(name: String): dynamic \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRoot.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRoot.kt similarity index 100% rename from dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRoot.kt rename to dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRoot.kt diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootDemoApp.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootDemoApp.kt similarity index 100% rename from dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootDemoApp.kt rename to dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootDemoApp.kt diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGEO.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootGEO.kt similarity index 100% rename from dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGEO.kt rename to dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootGEO.kt diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGeometry.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootGeometry.kt similarity index 92% rename from dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGeometry.kt rename to dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootGeometry.kt index 7eb159ab..46f44151 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootGeometry.kt +++ b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootGeometry.kt @@ -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 { diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootObject.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootObject.kt similarity index 75% rename from dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootObject.kt rename to dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootObject.kt index 9bf23b3a..c8d827ce 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootObject.kt +++ b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootObject.kt @@ -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 { } } -fun DisplayGroup.jsRootObject(str: String) { +fun VisualGroup.jsRootObject(str: String) { val json = JSON.parse(str) JSRootObject(this, EmptyMeta, json).also { add(it) } } \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootPlugin.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootPlugin.kt similarity index 100% rename from dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/jsroot/JSRootPlugin.kt rename to dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/JSRootPlugin.kt diff --git a/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/main.kt b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/main.kt new file mode 100644 index 00000000..97eda399 --- /dev/null +++ b/dataforge-vis-jsroot/src/main/kotlin/hep/dataforge/vis/jsroot/main.kt @@ -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 + + abstract fun start(state: Map) + abstract fun dispose(): Map +} + + +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()) + + application + } else { + null + } +} \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/resources/JSRootGeoBase.js b/dataforge-vis-jsroot/src/main/resources/JSRootGeoBase.js similarity index 99% rename from dataforge-vis-spatial-js/src/main/resources/JSRootGeoBase.js rename to dataforge-vis-jsroot/src/main/resources/JSRootGeoBase.js index 266a75ad..87cf8f12 100644 --- a/dataforge-vis-spatial-js/src/main/resources/JSRootGeoBase.js +++ b/dataforge-vis-jsroot/src/main/resources/JSRootGeoBase.js @@ -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 diff --git a/dataforge-vis-spatial-js/src/main/resources/JSRootUtils.js b/dataforge-vis-jsroot/src/main/resources/JSRootUtils.js similarity index 100% rename from dataforge-vis-spatial-js/src/main/resources/JSRootUtils.js rename to dataforge-vis-jsroot/src/main/resources/JSRootUtils.js diff --git a/dataforge-vis-spatial-js/src/main/resources/ThreeCSG.js b/dataforge-vis-jsroot/src/main/resources/ThreeCSG.js similarity index 100% rename from dataforge-vis-spatial-js/src/main/resources/ThreeCSG.js rename to dataforge-vis-jsroot/src/main/resources/ThreeCSG.js diff --git a/dataforge-vis-jsroot/src/main/web/index.html b/dataforge-vis-jsroot/src/main/web/index.html new file mode 100644 index 00000000..1f49cf4e --- /dev/null +++ b/dataforge-vis-jsroot/src/main/web/index.html @@ -0,0 +1,33 @@ + + + + + + Three js demo for particle physics + + + + +
+ Загрузить данные +
+ (перетащить файл сюда) +
+
+

Demo grid

+
+
+ + + + + + \ No newline at end of file diff --git a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/DisplayObjectFXListener.kt b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/DisplayObjectFXListener.kt index 7b8d0ed0..1fe12696 100644 --- a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/DisplayObjectFXListener.kt +++ b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/DisplayObjectFXListener.kt @@ -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?>>() init { diff --git a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt index 7be70525..3a11fd8c 100644 --- a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt +++ b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/FX3DOutput.kt @@ -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 { +class FX3DOutput(override val context: Context) : Output { 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 { 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 { } } - override fun render(obj: DisplayObject, meta: Meta) { + override fun render(obj: VisualObject, meta: Meta) { buildNode(obj)?.let { canvas.world.children.add(it) } } } \ No newline at end of file diff --git a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/RendererDemoApp.kt b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/RendererDemoApp.kt index b51ee3c8..e0778632 100644 --- a/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/RendererDemoApp.kt +++ b/dataforge-vis-spatial-fx/src/main/kotlin/hep/dataforge/vis/spatial/RendererDemoApp.kt @@ -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 { diff --git a/dataforge-vis-spatial-gdml/build.gradle.kts b/dataforge-vis-spatial-gdml/build.gradle.kts new file mode 100644 index 00000000..c66f1f0f --- /dev/null +++ b/dataforge-vis-spatial-gdml/build.gradle.kts @@ -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") + } + } + } +} \ No newline at end of file diff --git a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt new file mode 100644 index 00000000..e484039c --- /dev/null +++ b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt @@ -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 { +// return when(target){ +// ThreeFactory.TYPE-> mapOf("gdml".toName() to ThreeGDMLFactory) +// else -> emptyMap() +// } +// } +// +// companion object : PluginFactory { +// override val tag = PluginTag("vis.gdml", "hep.dataforge") +// override val type: KClass = GDMLPlugin::class +// override fun invoke(meta: Meta) = GDMLPlugin() +// } +//} \ No newline at end of file diff --git a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt new file mode 100644 index 00000000..dbde0130 --- /dev/null +++ b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt @@ -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::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) +// } +// +// +// } +// } +//} \ No newline at end of file diff --git a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt new file mode 100644 index 00000000..3f5f725d --- /dev/null +++ b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt @@ -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()} } +} \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt index 2dbc727d..b3397b16 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoApp.kt @@ -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,19 +19,16 @@ class ThreeDemoApp : ApplicationBase() { override val stateKeys: List = emptyList() override fun start(state: Map) { - 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"){ - box(100.0,100.0,100.0) { + demo("shapes", "Basic shapes") { + box(100.0, 100.0, 100.0) { z = 110.0 } - sphere(50.0){ + sphere(50.0) { x = 110 detail = 200 } @@ -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 { @@ -107,7 +102,7 @@ class ThreeDemoApp : ApplicationBase() { rotationY = PI / 4 } box(100, 100, 100) - color{ + color { "color" to Colors.lightgreen "opacity" to 0.3 } diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt index 4b179c31..558192fd 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/demo/ThreeDemoGrid.kt @@ -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()!! 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::class, name.toName(), meta = meta) + val output = get(VisualObject::class, name.toName(), meta = meta) output.render(action = block) } \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDML.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDML.kt deleted file mode 100644 index 6e33dfce..00000000 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDML.kt +++ /dev/null @@ -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() - - 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() - - 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} - } -} \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLNodes.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLNodes.kt deleted file mode 100644 index 40747435..00000000 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLNodes.kt +++ /dev/null @@ -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 { - 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 { - 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 { - 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 { - 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
{ - 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 { - override fun wrap(config: Config): GDMLXtru = GDMLXtru(config) - } -} - -internal class GDMLRefDelegate(val key: String?) : ReadWriteProperty { - 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 { - override fun wrap(config: Config): GDMLUnion = GDMLUnion(config) - } -} - -class GDMLSubtraction(config: Config) : GDMLBoolSolid(config) { - override val type: String = "subtraction" - - companion object : Specification { - override fun wrap(config: Config) = GDMLUnion(config) - } -} - -class GDMLIntersection(config: Config) : GDMLBoolSolid(config) { - override val type: String = "intersection" - - companion object : Specification { - override fun wrap(config: Config) = GDMLIntersection(config) - } -} \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt deleted file mode 100644 index 2f47760d..00000000 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/GDMLPlugin.kt +++ /dev/null @@ -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 { - return when(target){ - ThreeFactory.TYPE-> mapOf("gdml".toName() to ThreeGDMLFactory) - else -> emptyMap() - } - } - - companion object : PluginFactory { - override val tag = PluginTag("vis.gdml", "hep.dataforge") - override val type: KClass = GDMLPlugin::class - override fun invoke(meta: Meta) = GDMLPlugin() - } -} \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt deleted file mode 100644 index 0d335c37..00000000 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/gdml/ThreeGDMLFactory.kt +++ /dev/null @@ -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::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) - } - - - } - } -} \ No newline at end of file diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt index f524a127..70bd4116 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeFactory.kt @@ -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 { +interface ThreeFactory { val type: KClass @@ -34,7 +34,7 @@ interface ThreeFactory { companion object { const val TYPE = "threeFactory" - fun buildMesh(obj: T, geometryBuilder: (T) -> BufferGeometry): Mesh { + fun 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 { /** * 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 ThreeFactory.invoke(obj: Any): Object3D { +operator fun ThreeFactory.invoke(obj: Any): Object3D { if (type.isInstance(obj)) { return invoke(obj as T) } else { @@ -105,7 +105,7 @@ operator fun ThreeFactory.invoke(obj: Any): Object3D { /** * Basic geometry-based factory */ -abstract class MeshThreeFactory(override val type: KClass) : +abstract class MeshThreeFactory(override val type: KClass) : ThreeFactory { /** * Build a geometry for an object diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeOutput.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeOutput.kt index d1f06e2c..5536b6de 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeOutput.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/ThreeOutput.kt @@ -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 { +class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Output { override val context: Context get() = three.context @@ -58,7 +58,7 @@ class ThreeOutput(val three: ThreePlugin, val meta: Meta = EmptyMeta) : Output, ThreeFactory<*>>() + private val objectFactories = HashMap, ThreeFactory<*>>() private val compositeFactory = ThreeCompositeFactory(this) init { @@ -30,14 +30,14 @@ class ThreePlugin : AbstractPlugin() { objectFactories[Sphere::class] = ThreeSphereFactory } - private fun findObjectFactory(type: KClass): ThreeFactory<*>? { + private fun findObjectFactory(type: KClass): ThreeFactory<*>? { return objectFactories[type] ?: context.content>(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) diff --git a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/three.kt b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/three.kt index a7a3b9ea..02d88b8f 100644 --- a/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/three.kt +++ b/dataforge-vis-spatial-js/src/main/kotlin/hep/dataforge/vis/spatial/three/three.kt @@ -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) = 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) diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt index 9da53fbb..7f75f5c3 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Box.kt @@ -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() diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt index b38c47e5..653a5ae3 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Composite.kt @@ -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) \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt index ad2f7e12..55426f82 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Convex.kt @@ -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() diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt index b4c552a7..23473de0 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Extruded.kt @@ -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) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt index ddcf2ef5..befdcbb1 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/GeometryBuilder.kt @@ -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 toGeometry(geometryBuilder: GeometryBuilder) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt index ea75232c..501a5881 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/Sphere.kt @@ -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, diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt index 0d1fb8f8..7cbc28d4 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/displayObject3D.kt @@ -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.render(meta: Meta = EmptyMeta, action: DisplayGroup.() -> Unit) = - render(DisplayGroup(null, EmptyMeta).apply(action), meta) +fun Output.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.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.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 diff --git a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt index bd375a72..48a93aa6 100644 --- a/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt +++ b/dataforge-vis-spatial/src/commonTest/kotlin/hep/dataforge/vis/spatial/ConvexTest.kt @@ -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) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 87b738cbd051603d91cc39de6cb000dd98fe6b02..5c2d1cf016b3885f6930543d57b744ea8c220a1a 100644 GIT binary patch delta 3320 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