forked from kscience/visionforge
Major caching update for objects
This commit is contained in:
parent
073ae8a353
commit
c3a7afc6d0
@ -0,0 +1,130 @@
|
||||
package hep.dataforge.vis.common
|
||||
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.get
|
||||
import hep.dataforge.provider.Provider
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlin.collections.set
|
||||
|
||||
open class VisualGroup<T : VisualObject> : AbstractVisualObject(), Iterable<T>, Provider {
|
||||
|
||||
protected val namedChildren = HashMap<Name, T>()
|
||||
protected val unnamedChildren = ArrayList<T>()
|
||||
|
||||
override val defaultTarget: String get() = VisualObject.TYPE
|
||||
|
||||
override fun iterator(): Iterator<T> = (namedChildren.values + unnamedChildren).iterator()
|
||||
|
||||
override fun provideTop(target: String): Map<Name, Any> {
|
||||
return when (target) {
|
||||
VisualObject.TYPE -> namedChildren
|
||||
else -> emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
|
||||
super.propertyChanged(name, before, after)
|
||||
forEach {
|
||||
it.propertyChanged(name, before, after)
|
||||
}
|
||||
}
|
||||
|
||||
private data class Listener<T : VisualObject>(val owner: Any?, val callback: (Name?, T?) -> Unit)
|
||||
|
||||
@Transient
|
||||
private val listeners = HashSet<Listener<T>>()
|
||||
|
||||
/**
|
||||
* Add listener for children change
|
||||
*/
|
||||
fun onChildrenChange(owner: Any?, action: (Name?, T?) -> Unit) {
|
||||
listeners.add(Listener(owner, action))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove children change listener
|
||||
*/
|
||||
fun removeChildrenChangeListener(owner: Any?) {
|
||||
listeners.removeAll { it.owner === owner }
|
||||
}
|
||||
|
||||
operator fun set(name: Name, child: T?) {
|
||||
if (child == null) {
|
||||
namedChildren.remove(name)
|
||||
} else {
|
||||
if (child.parent == null) {
|
||||
child.parent = this
|
||||
} else {
|
||||
error("Can't reassign existing parent for $child")
|
||||
}
|
||||
namedChildren[name] = child
|
||||
}
|
||||
listeners.forEach { it.callback(name, child) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Add named or unnamed child to the group. If key is [null] the child is considered unnamed. Both key and value are not
|
||||
* allowed to be null in the same time. If name is present and [child] is null, the appropriate element is removed.
|
||||
*/
|
||||
operator fun set(name: Name?, child: T?) {
|
||||
when {
|
||||
name != null -> set(name, child)
|
||||
child != null -> add(child)
|
||||
else -> error("Both key and child element are empty")
|
||||
}
|
||||
}
|
||||
|
||||
operator fun set(key: String?, child: T?) = set(key?.asName(), child)
|
||||
|
||||
/**
|
||||
* Get named child by name
|
||||
*/
|
||||
operator fun get(name: Name): T? = namedChildren[name]
|
||||
|
||||
/**
|
||||
* Get named child by string
|
||||
*/
|
||||
operator fun get(key: String): T? = namedChildren.get(key)
|
||||
|
||||
/**
|
||||
* Get an unnamed child
|
||||
*/
|
||||
operator fun get(index: Int): T? = unnamedChildren[index]
|
||||
|
||||
/**
|
||||
* Append unnamed child
|
||||
*/
|
||||
fun add(child: T) {
|
||||
if (child.parent == null) {
|
||||
child.parent = this
|
||||
} else {
|
||||
error("Can't reassign existing parent for $child")
|
||||
}
|
||||
unnamedChildren.add(child)
|
||||
listeners.forEach { it.callback(null, child) }
|
||||
}
|
||||
|
||||
/**
|
||||
* remove unnamed child
|
||||
*/
|
||||
fun remove(child: VisualObject) {
|
||||
unnamedChildren.remove(child)
|
||||
listeners.forEach { it.callback(null, null) }
|
||||
}
|
||||
|
||||
protected fun MetaBuilder.updateChildren() {
|
||||
//adding unnamed children
|
||||
"unnamedChildren" to unnamedChildren.map { it.toMeta() }
|
||||
//adding named children
|
||||
namedChildren.forEach {
|
||||
"children[${it.key}]" to it.value.toMeta()
|
||||
}
|
||||
}
|
||||
|
||||
override fun MetaBuilder.updateMeta() {
|
||||
updateChildren()
|
||||
}
|
||||
}
|
@ -6,10 +6,7 @@ import hep.dataforge.names.Name
|
||||
/**
|
||||
* Basic [VisualObject] leaf element
|
||||
*/
|
||||
open class VisualLeaf(
|
||||
parent: VisualObject? = null,
|
||||
meta: Meta = EmptyMeta
|
||||
) : AbstractVisualObject(parent), Configurable {
|
||||
open class VisualLeaf(meta: Meta = EmptyMeta) : AbstractVisualObject(), Configurable {
|
||||
|
||||
val properties = Styled(meta)
|
||||
|
||||
|
@ -1,12 +1,13 @@
|
||||
package hep.dataforge.vis.common
|
||||
|
||||
import hep.dataforge.io.ConfigSerializer
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.get
|
||||
import hep.dataforge.provider.Provider
|
||||
import hep.dataforge.provider.Type
|
||||
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
|
||||
import kotlin.collections.set
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
|
||||
private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
||||
private fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
||||
@ -22,7 +23,8 @@ interface VisualObject : MetaRepr, Configurable {
|
||||
/**
|
||||
* The parent object of this one. If null, this one is a root.
|
||||
*/
|
||||
val parent: VisualObject?
|
||||
@Transient
|
||||
var parent: VisualObject?
|
||||
|
||||
/**
|
||||
* Set property for this object
|
||||
@ -62,8 +64,10 @@ internal data class MetaListener(
|
||||
val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
|
||||
)
|
||||
|
||||
abstract class AbstractVisualObject : VisualObject {
|
||||
override var parent: VisualObject? = null
|
||||
|
||||
abstract class AbstractVisualObject(override val parent: VisualObject?) : VisualObject {
|
||||
@Transient
|
||||
private val listeners = HashSet<MetaListener>()
|
||||
|
||||
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
|
||||
@ -80,6 +84,8 @@ abstract class AbstractVisualObject(override val parent: VisualObject?) : Visual
|
||||
listeners.removeAll { it.owner == owner }
|
||||
}
|
||||
|
||||
@Serializable(ConfigSerializer::class)
|
||||
@SerialName("properties")
|
||||
private var _config: Config? = null
|
||||
override val config: Config
|
||||
get() = _config ?: Config().also { config ->
|
||||
@ -103,117 +109,9 @@ abstract class AbstractVisualObject(override val parent: VisualObject?) : Visual
|
||||
|
||||
override fun toMeta(): Meta = buildMeta {
|
||||
"type" to type
|
||||
"properties" to _config
|
||||
"properties" to config
|
||||
updateMeta()
|
||||
}
|
||||
}
|
||||
|
||||
open class VisualGroup<T : VisualObject>(parent: VisualObject?) : AbstractVisualObject(parent), Iterable<T>, Provider {
|
||||
|
||||
protected val namedChildren = HashMap<Name, T>()
|
||||
protected val unnamedChildren = ArrayList<T>()
|
||||
|
||||
override val defaultTarget: String get() = VisualObject.TYPE
|
||||
|
||||
override fun iterator(): Iterator<T> = (namedChildren.values + unnamedChildren).iterator()
|
||||
|
||||
override fun provideTop(target: String): Map<Name, Any> {
|
||||
return when (target) {
|
||||
TYPE -> namedChildren
|
||||
else -> emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
|
||||
super.propertyChanged(name, before, after)
|
||||
forEach {
|
||||
it.propertyChanged(name, before, after)
|
||||
}
|
||||
}
|
||||
|
||||
private data class Listener<T : VisualObject>(val owner: Any?, val callback: (Name?, T?) -> Unit)
|
||||
|
||||
private val listeners = HashSet<Listener<T>>()
|
||||
|
||||
/**
|
||||
* Add listener for children change
|
||||
*/
|
||||
fun onChildrenChange(owner: Any?, action: (Name?, T?) -> Unit) {
|
||||
listeners.add(Listener(owner, action))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove children change listener
|
||||
*/
|
||||
fun removeChildrenChangeListener(owner: Any?) {
|
||||
listeners.removeAll { it.owner === owner }
|
||||
}
|
||||
|
||||
/**
|
||||
* Add named or unnamed child to the group. If key is [null] the child is considered unnamed. Both key and value are not
|
||||
* allowed to be null in the same time. If name is present and [child] is null, the appropriate element is removed.
|
||||
*/
|
||||
operator fun set(name: Name?, child: T?) {
|
||||
when {
|
||||
name != null -> {
|
||||
if (child == null) {
|
||||
namedChildren.remove(name)
|
||||
} else {
|
||||
namedChildren[name] = child
|
||||
}
|
||||
listeners.forEach { it.callback(name, child) }
|
||||
}
|
||||
child != null -> unnamedChildren.add(child)
|
||||
else -> error("Both key and child element are empty")
|
||||
}
|
||||
}
|
||||
|
||||
operator fun set(key: String?, child: T?) = set(key?.asName(), child)
|
||||
|
||||
/**
|
||||
* Get named child by name
|
||||
*/
|
||||
operator fun get(name: Name): T? = namedChildren[name]
|
||||
|
||||
/**
|
||||
* Get named child by string
|
||||
*/
|
||||
operator fun get(key: String): T? = namedChildren[key]
|
||||
|
||||
/**
|
||||
* Get an unnamed child
|
||||
*/
|
||||
operator fun get(index: Int): T? = unnamedChildren[index]
|
||||
|
||||
/**
|
||||
* Append unnamed child
|
||||
*/
|
||||
fun add(child: T) {
|
||||
unnamedChildren.add(child)
|
||||
listeners.forEach { it.callback(null, child) }
|
||||
}
|
||||
|
||||
/**
|
||||
* remove unnamed child
|
||||
*/
|
||||
fun remove(child: VisualObject) {
|
||||
unnamedChildren.remove(child)
|
||||
listeners.forEach { it.callback(null, null) }
|
||||
}
|
||||
|
||||
protected fun MetaBuilder.updateChildren() {
|
||||
//adding unnamed children
|
||||
"children" to unnamedChildren.map { it.toMeta() }
|
||||
//adding named children
|
||||
namedChildren.forEach {
|
||||
"children[${it.key}" to it.value.toMeta()
|
||||
}
|
||||
}
|
||||
|
||||
override fun MetaBuilder.updateMeta() {
|
||||
updateChildren()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,37 @@
|
||||
package hep.dataforge.vis.common
|
||||
|
||||
import hep.dataforge.context.*
|
||||
import hep.dataforge.meta.Meta
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
interface VisualFactory<T : VisualObject> {
|
||||
val type: KClass<T>
|
||||
operator fun invoke(
|
||||
context: Context,
|
||||
parent: VisualObject?,
|
||||
meta: Meta
|
||||
): T
|
||||
}
|
||||
|
||||
class VisualPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
/**
|
||||
* Create a list of factories on first call and cache it
|
||||
*/
|
||||
val visualFactories by lazy {
|
||||
context.content<VisualFactory<*>>(VISUAL_FACTORY_TYPE).mapKeys { it.value.type }
|
||||
}
|
||||
|
||||
inline fun <reified T : VisualObject> buildVisual(parent: VisualObject?, meta: Meta): T? {
|
||||
return visualFactories[T::class]?.invoke(context, parent, meta) as T?
|
||||
}
|
||||
|
||||
companion object : PluginFactory<VisualPlugin> {
|
||||
override val tag: PluginTag = PluginTag(name = "visual", group = PluginTag.DATAFORGE_GROUP)
|
||||
override val type: KClass<out VisualPlugin> = VisualPlugin::class
|
||||
override fun invoke(meta: Meta): VisualPlugin = VisualPlugin(meta)
|
||||
|
||||
const val VISUAL_FACTORY_TYPE = "visual.factory"
|
||||
}
|
||||
}
|
@ -96,14 +96,14 @@ class FXMetaNode<M : MetaNode<M>>(
|
||||
if (name.length == 1) invalidate()
|
||||
}
|
||||
|
||||
(node as? MutableMeta<*>)?.onChange(this, listener)
|
||||
(node as? Config)?.onChange(this, listener)
|
||||
|
||||
nodeProperty.addListener { _, oldValue, newValue ->
|
||||
if (newValue == null) {
|
||||
(oldValue as? MutableMeta<*>)?.removeListener(this)
|
||||
(oldValue as? Config)?.removeListener(this)
|
||||
}
|
||||
|
||||
if (newValue is MutableMeta<*>) {
|
||||
if (newValue is Config) {
|
||||
newValue.onChange(this, listener)
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,11 @@ kotlin {
|
||||
val commonMain by getting {
|
||||
dependencies {
|
||||
api(project(":dataforge-vis-spatial"))
|
||||
api("scientifik:gdml:0.1.3")
|
||||
api("scientifik:gdml:0.1.4-dev-1")
|
||||
}
|
||||
}
|
||||
val jsMain by getting{
|
||||
dependencies{
|
||||
val jsMain by getting {
|
||||
dependencies {
|
||||
api(project(":dataforge-vis-spatial-js"))
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,12 @@ class GDMLTransformer(val root: GDML) {
|
||||
private val materialCache = HashMap<GDMLMaterial, Meta>()
|
||||
private val random = Random(111)
|
||||
|
||||
enum class Action{
|
||||
ACCEPT,
|
||||
REJECT,
|
||||
CACHE
|
||||
}
|
||||
|
||||
/**
|
||||
* A special group for local templates
|
||||
*/
|
||||
@ -34,15 +40,15 @@ class GDMLTransformer(val root: GDML) {
|
||||
}
|
||||
}
|
||||
|
||||
var acceptSolid: (GDMLSolid) -> Boolean = { true }
|
||||
var acceptGroup: (GDMLGroup) -> Boolean = { true }
|
||||
var solidAction: (GDMLSolid) -> Action = { Action.CACHE }
|
||||
var volumeAction: (GDMLGroup) -> Action = { Action.ACCEPT }
|
||||
|
||||
fun printStatistics() {
|
||||
println("Solids:")
|
||||
solidCounter.entries.sortedByDescending { it.value }.forEach {
|
||||
println("\t$it")
|
||||
}
|
||||
println(println("Solids total: ${solidCounter.values.sum()}"))
|
||||
println("Solids total: ${solidCounter.values.sum()}")
|
||||
}
|
||||
|
||||
private val solidCounter = HashMap<String, Int>()
|
||||
@ -53,8 +59,9 @@ class GDMLTransformer(val root: GDML) {
|
||||
|
||||
var onFinish: GDMLTransformer.() -> Unit = {}
|
||||
|
||||
internal fun finished() {
|
||||
onFinish(this)
|
||||
internal fun finished(final: VisualGroup3D) {
|
||||
final.templates = templates
|
||||
onFinish(this@GDMLTransformer)
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package hep.dataforge.vis.spatial.gdml
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.vis.common.asName
|
||||
import hep.dataforge.vis.spatial.*
|
||||
import scientifik.gdml.*
|
||||
import kotlin.math.cos
|
||||
@ -131,6 +133,8 @@ private fun VisualGroup3D.addSolid(
|
||||
}.apply(block)
|
||||
}
|
||||
|
||||
private val volumesName = "volumes".asName()
|
||||
|
||||
private fun VisualGroup3D.addPhysicalVolume(
|
||||
context: GDMLTransformer,
|
||||
physVolume: GDMLPhysVolume
|
||||
@ -138,15 +142,35 @@ private fun VisualGroup3D.addPhysicalVolume(
|
||||
val volume: GDMLGroup = physVolume.volumeref.resolve(context.root)
|
||||
?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved")
|
||||
|
||||
if (context.acceptGroup(volume)) {
|
||||
when (context.volumeAction(volume)) {
|
||||
GDMLTransformer.Action.ACCEPT -> {
|
||||
this[physVolume.name] = volume(context, volume).apply {
|
||||
withPosition(
|
||||
context.lUnit,
|
||||
physVolume.resolvePosition(context.root),
|
||||
physVolume.resolveRotation(context.root),
|
||||
physVolume.resolveScale(context.root)
|
||||
)
|
||||
}
|
||||
}
|
||||
GDMLTransformer.Action.CACHE -> {
|
||||
val name = volumesName + volume.name.asName()
|
||||
if (context.templates[name] == null) {
|
||||
context.templates[name] = volume(context, volume)
|
||||
}
|
||||
|
||||
this[physVolume.name] = volume(
|
||||
context,
|
||||
volume,
|
||||
physVolume.resolvePosition(context.root),
|
||||
physVolume.resolveRotation(context.root),
|
||||
physVolume.resolveScale(context.root)
|
||||
)
|
||||
this[physVolume.name] = Proxy(name).apply {
|
||||
withPosition(
|
||||
context.lUnit,
|
||||
physVolume.resolvePosition(context.root),
|
||||
physVolume.resolveRotation(context.root),
|
||||
physVolume.resolveScale(context.root)
|
||||
)
|
||||
}
|
||||
}
|
||||
GDMLTransformer.Action.REJECT -> {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,36 +192,38 @@ private fun VisualGroup3D.addDivisionVolume(
|
||||
|
||||
private fun VisualGroup3D.addVolume(
|
||||
context: GDMLTransformer,
|
||||
group: GDMLGroup,
|
||||
position: GDMLPosition? = null,
|
||||
rotation: GDMLRotation? = null,
|
||||
scale: GDMLScale? = null
|
||||
group: GDMLGroup
|
||||
) {
|
||||
this[group.name] = volume(context, group, position, rotation, scale)
|
||||
this[group.name] = volume(context, group)
|
||||
}
|
||||
|
||||
private fun volume(
|
||||
context: GDMLTransformer,
|
||||
group: GDMLGroup,
|
||||
position: GDMLPosition? = null,
|
||||
rotation: GDMLRotation? = null,
|
||||
scale: GDMLScale? = null
|
||||
group: GDMLGroup
|
||||
): VisualGroup3D {
|
||||
|
||||
return VisualGroup3D().apply {
|
||||
withPosition(context.lUnit, position, rotation, scale)
|
||||
|
||||
if (group is GDMLVolume) {
|
||||
val solid = group.solidref.resolve(context.root)
|
||||
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
|
||||
val material = group.materialref.resolve(context.root) ?: GDMLElement(group.materialref.ref)
|
||||
|
||||
if (context.acceptSolid(solid)) {
|
||||
val cachedSolid = context.templates[solid.name]
|
||||
?: context.templates.addSolid(context, solid, solid.name) {
|
||||
when (context.solidAction(solid)) {
|
||||
GDMLTransformer.Action.ACCEPT -> {
|
||||
addSolid(context, solid, solid.name) {
|
||||
this.material = context.resolveColor(group, material, solid)
|
||||
}
|
||||
proxy(cachedSolid, solid.name)
|
||||
}
|
||||
GDMLTransformer.Action.CACHE -> {
|
||||
if (context.templates[solid.name] == null) {
|
||||
context.templates.addSolid(context, solid, solid.name) {
|
||||
this.material = context.resolveColor(group, material, solid)
|
||||
}
|
||||
}
|
||||
ref(solid.name.asName(), solid.name)
|
||||
}
|
||||
GDMLTransformer.Action.REJECT -> {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
|
||||
when (val vol = group.placement) {
|
||||
@ -220,6 +246,6 @@ fun GDML.toVisual(block: GDMLTransformer.() -> Unit = {}): VisualGroup3D {
|
||||
val context = GDMLTransformer(this).apply(block)
|
||||
|
||||
return volume(context, world).also {
|
||||
context.finished()
|
||||
context.finished(it)
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package hep.dataforge.vis.spatial.gdml.demo
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.vis.hmr.ApplicationBase
|
||||
import hep.dataforge.vis.hmr.startApplication
|
||||
import hep.dataforge.vis.spatial.gdml.GDMLTransformer
|
||||
import hep.dataforge.vis.spatial.gdml.LUnit
|
||||
import hep.dataforge.vis.spatial.gdml.toVisual
|
||||
import hep.dataforge.vis.spatial.three.ThreePlugin
|
||||
@ -82,7 +83,7 @@ private class GDMLDemoApp : ApplicationBase() {
|
||||
val canvas = document.getElementById("canvas") ?: error("Element with id canvas not found on page")
|
||||
canvas.clear()
|
||||
|
||||
val action: suspend CoroutineScope.(String) -> Unit = {
|
||||
val action: suspend CoroutineScope.(String) -> Unit = { it ->
|
||||
canvas.clear()
|
||||
launch { spinner(true) }
|
||||
launch { message("Loading GDML") }
|
||||
@ -90,11 +91,15 @@ private class GDMLDemoApp : ApplicationBase() {
|
||||
launch { message("Converting GDML into DF-VIS format") }
|
||||
val visual = gdml.toVisual {
|
||||
lUnit = LUnit.CM
|
||||
acceptSolid = { solid ->
|
||||
!solid.name.startsWith("ecal")
|
||||
// && !solid.name.startsWith("V")
|
||||
// && !solid.name.startsWith("U")
|
||||
volumeAction = { volume ->
|
||||
when {
|
||||
volume.name.startsWith("ecal") -> GDMLTransformer.Action.REJECT
|
||||
volume.name.startsWith("U") -> GDMLTransformer.Action.CACHE
|
||||
volume.name.startsWith("V") -> GDMLTransformer.Action.CACHE
|
||||
else -> GDMLTransformer.Action.ACCEPT
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
launch { message("Rendering") }
|
||||
val output = three.output(canvas)
|
||||
|
@ -1,25 +1,38 @@
|
||||
package hep.dataforge.vis.spatial.gdml
|
||||
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||
import nl.adaptivity.xmlutil.StAXReader
|
||||
import scientifik.gdml.GDML
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
|
||||
fun main() {
|
||||
val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
||||
val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\BM@N.gdml")
|
||||
val stream = if (file.exists()) {
|
||||
file.inputStream()
|
||||
} else {
|
||||
url.openStream()
|
||||
}
|
||||
//val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml")
|
||||
|
||||
val xmlReader = StAXReader(stream, "UTF-8")
|
||||
val xmlReader = StAXReader(file.inputStream(), "UTF-8")
|
||||
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||
xml.toVisual {
|
||||
val visual = xml.toVisual {
|
||||
lUnit = LUnit.CM
|
||||
//acceptSolid = { solid -> !solid.name.startsWith("ecal") && !solid.name.startsWith("V") }
|
||||
volumeAction = { volume ->
|
||||
when {
|
||||
volume.name.startsWith("ecal") -> GDMLTransformer.Action.CACHE
|
||||
volume.name.startsWith("U") -> GDMLTransformer.Action.CACHE
|
||||
volume.name.startsWith("V") -> GDMLTransformer.Action.CACHE
|
||||
else -> GDMLTransformer.Action.ACCEPT
|
||||
}
|
||||
}
|
||||
onFinish = { printStatistics() }
|
||||
}
|
||||
readLine()
|
||||
|
||||
val template = visual.getTemplate("volumes.ecal01mod".toName())
|
||||
println(template)
|
||||
visual.flatMap { (it as? VisualGroup3D) ?: listOf(it) }.forEach {
|
||||
if(it.parent==null) error("")
|
||||
}
|
||||
//readLine()
|
||||
//val meta = visual.toMeta()
|
||||
// val tmpFile = File.createTempFile("dataforge-visual", "json")
|
||||
//tmpFile.writeText(meta.toString())
|
||||
//println(tmpFile.absoluteFile)
|
||||
}
|
@ -49,7 +49,7 @@ class ThreePlugin : AbstractPlugin() {
|
||||
updatePosition(obj)
|
||||
}
|
||||
is Composite -> compositeFactory(obj)
|
||||
is Proxy3D -> proxyFactory(obj)
|
||||
is Proxy -> proxyFactory(obj)
|
||||
else -> {
|
||||
//find specialized factory for this type if it is present
|
||||
val factory = findObjectFactory(obj::class)
|
||||
@ -84,7 +84,7 @@ class ThreePlugin : AbstractPlugin() {
|
||||
}
|
||||
|
||||
companion object : PluginFactory<ThreePlugin> {
|
||||
override val tag = PluginTag("vis.three", "hep.dataforge")
|
||||
override val tag = PluginTag("visual.three", PluginTag.DATAFORGE_GROUP)
|
||||
override val type = ThreePlugin::class
|
||||
override fun invoke(meta: Meta) = ThreePlugin()
|
||||
}
|
||||
|
@ -1,22 +1,22 @@
|
||||
package hep.dataforge.vis.spatial.three
|
||||
|
||||
import hep.dataforge.vis.spatial.Proxy3D
|
||||
import hep.dataforge.vis.spatial.Proxy
|
||||
import hep.dataforge.vis.spatial.VisualObject3D
|
||||
import info.laht.threekt.core.Object3D
|
||||
import info.laht.threekt.objects.Mesh
|
||||
|
||||
class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy3D> {
|
||||
private val cache = HashMap<VisualObject3D, Mesh>()
|
||||
class ThreeProxyFactory(val three: ThreePlugin) : ThreeFactory<Proxy> {
|
||||
private val cache = HashMap<VisualObject3D, Object3D>()
|
||||
|
||||
override val type = Proxy3D::class
|
||||
override val type = Proxy::class
|
||||
|
||||
override fun invoke(obj: Proxy3D): Object3D {
|
||||
val templateMesh = cache.getOrPut(obj.template) {
|
||||
three.buildObject3D(obj.template) as Mesh
|
||||
override fun invoke(obj: Proxy): Object3D {
|
||||
val template = obj.template
|
||||
val cachedObject = cache.getOrPut(template) {
|
||||
three.buildObject3D(template)
|
||||
}
|
||||
|
||||
//val mesh = Mesh(templateMesh.geometry as BufferGeometry, templateMesh.material)
|
||||
val mesh = templateMesh.clone()
|
||||
val mesh = cachedObject.clone()
|
||||
|
||||
mesh.updatePosition(obj)
|
||||
return mesh
|
||||
|
@ -2,13 +2,34 @@ plugins {
|
||||
id("scientifik.mpp")
|
||||
}
|
||||
|
||||
scientifik{
|
||||
serialization = true
|
||||
}
|
||||
|
||||
kotlin {
|
||||
jvm{
|
||||
withJava()
|
||||
}
|
||||
sourceSets {
|
||||
val commonMain by getting {
|
||||
commonMain {
|
||||
dependencies {
|
||||
api(project(":dataforge-vis-common"))
|
||||
}
|
||||
}
|
||||
jvmMain{
|
||||
dependencies {
|
||||
|
||||
}
|
||||
}
|
||||
jsMain{
|
||||
dependencies {
|
||||
api("info.laht.threekt:threejs-wrapper:0.106-npm-3")
|
||||
implementation(npm("three", "0.106.2"))
|
||||
implementation(npm("@hi-level/three-csg"))
|
||||
implementation(npm("style-loader"))
|
||||
implementation(npm("element-resize-event"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,19 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.float
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.vis.common.VisualFactory
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class Box(parent: VisualObject?, val xSize: Number, val ySize: Number, val zSize: Number) :
|
||||
VisualLeaf3D(parent), Shape {
|
||||
data class Box(
|
||||
val xSize: Float,
|
||||
val ySize: Float,
|
||||
val zSize: Float
|
||||
) : VisualLeaf3D(), Shape {
|
||||
|
||||
//TODO add helper for color configuration
|
||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||
@ -26,9 +36,24 @@ class Box(parent: VisualObject?, val xSize: Number, val ySize: Number, val zSize
|
||||
geometryBuilder.face4(node8, node5, node6, node7)
|
||||
}
|
||||
|
||||
companion object {
|
||||
override fun MetaBuilder.updateMeta() {
|
||||
"xSize" to xSize
|
||||
"ySize" to ySize
|
||||
"zSize" to ySize
|
||||
}
|
||||
|
||||
companion object : VisualFactory<Box> {
|
||||
const val TYPE = "geometry.3d.box"
|
||||
|
||||
override val type: KClass<Box> get() = Box::class
|
||||
|
||||
override fun invoke(context: Context, parent: VisualObject?, meta: Meta): Box = Box(
|
||||
meta["xSize"].float!!,
|
||||
meta["ySize"].float!!,
|
||||
meta["zSize"].float!!
|
||||
).apply {
|
||||
update(meta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,4 +63,4 @@ inline fun VisualGroup3D.box(
|
||||
zSize: Number,
|
||||
name: String? = null,
|
||||
action: Box.() -> Unit = {}
|
||||
) = Box(this, xSize, ySize, zSize).apply(action).also { set(name, it) }
|
||||
) = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(action).also { set(name, it) }
|
@ -2,7 +2,6 @@ package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.meta.isEmpty
|
||||
import hep.dataforge.meta.update
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
|
||||
enum class CompositeType {
|
||||
UNION,
|
||||
@ -11,13 +10,12 @@ enum class CompositeType {
|
||||
}
|
||||
|
||||
open class Composite(
|
||||
parent: VisualObject?,
|
||||
val first: VisualObject3D,
|
||||
val second: VisualObject3D,
|
||||
val compositeType: CompositeType = CompositeType.UNION
|
||||
) : VisualLeaf3D(parent)
|
||||
) : VisualLeaf3D()
|
||||
|
||||
fun VisualGroup3D.composite(
|
||||
inline fun VisualGroup3D.composite(
|
||||
type: CompositeType,
|
||||
name: String? = null,
|
||||
builder: VisualGroup3D.() -> Unit
|
||||
@ -25,7 +23,7 @@ fun VisualGroup3D.composite(
|
||||
val group = VisualGroup3D().apply(builder)
|
||||
val children = group.filterIsInstance<VisualObject3D>()
|
||||
if (children.size != 2) error("Composite requires exactly two children")
|
||||
return Composite(this, children[0], children[1], type).also {
|
||||
return Composite(children[0], children[1], type).also {
|
||||
if (!group.config.isEmpty()) {
|
||||
it.config.update(group.config)
|
||||
}
|
||||
|
@ -1,17 +1,24 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
|
||||
class Convex(parent: VisualObject?, val points: List<Point3D>) : VisualLeaf3D(parent) {
|
||||
class Convex(
|
||||
val points: List<Point3D>
|
||||
) : VisualLeaf3D() {
|
||||
|
||||
override fun MetaBuilder.updateMeta() {
|
||||
"points" to {
|
||||
"point" to points.map{it.toMeta()}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val TYPE = "geometry.3d.convex"
|
||||
}
|
||||
}
|
||||
|
||||
fun VisualGroup3D.convex(action: ConvexBuilder.() -> Unit = {}) =
|
||||
ConvexBuilder().apply(action).build(this).also { add(it) }
|
||||
inline fun VisualGroup3D.convex(name: String? = null, action: ConvexBuilder.() -> Unit = {}) =
|
||||
ConvexBuilder().apply(action).build().also { set(name, it) }
|
||||
|
||||
class ConvexBuilder {
|
||||
private val points = ArrayList<Point3D>()
|
||||
@ -20,7 +27,7 @@ class ConvexBuilder {
|
||||
points.add(Point3D(x, y, z))
|
||||
}
|
||||
|
||||
fun build(parent: VisualObject?): Convex {
|
||||
return Convex(parent, points)
|
||||
fun build(): Convex {
|
||||
return Convex(points)
|
||||
}
|
||||
}
|
@ -1,27 +1,22 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import kotlin.math.PI
|
||||
|
||||
/**
|
||||
* A cylinder or cut cone segment
|
||||
*/
|
||||
class Cylinder(
|
||||
parent: VisualObject?,
|
||||
var radius: Number,
|
||||
var height: Number,
|
||||
var upperRadius: Number = radius,
|
||||
var startAngle: Number = 0f,
|
||||
var angle: Number = 2 * PI
|
||||
) : VisualLeaf3D(parent)
|
||||
var radius: Float,
|
||||
var height: Float,
|
||||
var upperRadius: Float = radius,
|
||||
var startAngle: Float = 0f,
|
||||
var angle: Float = PI2
|
||||
) : VisualLeaf3D()
|
||||
|
||||
fun VisualGroup3D.cylinder(
|
||||
inline fun VisualGroup3D.cylinder(
|
||||
r: Number,
|
||||
height: Number,
|
||||
name: String? = null,
|
||||
block: Cylinder.() -> Unit = {}
|
||||
): Cylinder {
|
||||
val cylinder = Cylinder(this, r, height)
|
||||
cylinder.apply(block)
|
||||
return cylinder.also { set(name, it) }
|
||||
}
|
||||
): Cylinder = Cylinder(
|
||||
r.toFloat(),
|
||||
height.toFloat()
|
||||
).apply(block).also { set(name, it) }
|
@ -1,6 +1,5 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
@ -30,7 +29,7 @@ fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
|
||||
|
||||
data class Layer(var x: Number, var y: Number, var z: Number, var scale: Number)
|
||||
|
||||
class Extruded(parent: VisualObject?) : VisualLeaf3D(parent), Shape {
|
||||
class Extruded : VisualLeaf3D(), Shape {
|
||||
|
||||
var shape: List<Point2D> = ArrayList()
|
||||
|
||||
@ -98,4 +97,4 @@ class Extruded(parent: VisualObject?) : VisualLeaf3D(parent), Shape {
|
||||
}
|
||||
|
||||
fun VisualGroup3D.extrude(name: String? = null, action: Extruded.() -> Unit = {}) =
|
||||
Extruded(this).apply(action).also { set(name, it) }
|
||||
Extruded().apply(action).also { set(name, it) }
|
@ -0,0 +1,54 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.vis.common.AbstractVisualObject
|
||||
|
||||
/**
|
||||
* A proxy [VisualObject3D] to reuse a template object
|
||||
*/
|
||||
class Proxy(val templateName: Name) : AbstractVisualObject(), VisualObject3D {
|
||||
override var position: Value3 = Value3()
|
||||
override var rotation: Value3 = Value3()
|
||||
override var scale: Value3 = Value3(1f, 1f, 1f)
|
||||
|
||||
val template by lazy { getTemplate() }
|
||||
|
||||
/**
|
||||
* Recursively search for defined template in the parent
|
||||
*/
|
||||
private fun getTemplate(): VisualObject3D {
|
||||
return (parent as? VisualGroup3D)?.getTemplate(templateName)
|
||||
?: error("Template with name $templateName not found in $parent")
|
||||
}
|
||||
|
||||
|
||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||
return if (inherit) {
|
||||
super.getProperty(name, false) ?: template.getProperty(name, false) ?: parent?.getProperty(name, inherit)
|
||||
} else {
|
||||
super.getProperty(name, false) ?: template.getProperty(name, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun MetaBuilder.updateMeta() {
|
||||
//TODO add reference to child
|
||||
updatePosition()
|
||||
}
|
||||
}
|
||||
|
||||
//fun VisualGroup3D.proxy(
|
||||
// templateName: Name,
|
||||
// //name: String? = null,
|
||||
// builder: VisualGroup3D.() -> Unit
|
||||
//): Proxy {
|
||||
// val template = getTemplate(templateName) ?: templates.builder()
|
||||
// return Proxy(this, templateName).also { set(name, it) }
|
||||
//}
|
||||
|
||||
inline fun VisualGroup3D.ref(
|
||||
templateName: Name,
|
||||
name: String? = null,
|
||||
action: Proxy.() -> Unit = {}
|
||||
) = Proxy(templateName).apply(action).also { set(name, it) }
|
@ -1,34 +0,0 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.vis.common.AbstractVisualObject
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
|
||||
/**
|
||||
* A proxy [VisualObject3D] to reuse a [template] object
|
||||
*/
|
||||
class Proxy3D(parent: VisualObject?, val template: VisualObject3D) : AbstractVisualObject(parent), VisualObject3D {
|
||||
override var position: Value3 = Value3()
|
||||
override var rotation: Value3 = Value3()
|
||||
override var scale: Value3 = Value3(1f, 1f, 1f)
|
||||
|
||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||
return if (inherit) {
|
||||
super.getProperty(name, false) ?: template.getProperty(name, false) ?: parent?.getProperty(name, inherit)
|
||||
} else {
|
||||
super.getProperty(name, false) ?: template.getProperty(name, false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun MetaBuilder.updateMeta() {
|
||||
updatePosition()
|
||||
}
|
||||
}
|
||||
|
||||
inline fun VisualGroup3D.proxy(
|
||||
template: VisualObject3D,
|
||||
name: String? = null,
|
||||
action: Proxy3D.() -> Unit = {}
|
||||
) = Proxy3D(this, template).apply(action).also { set(name, it) }
|
@ -1,23 +1,23 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import hep.dataforge.vis.common.number
|
||||
import kotlin.math.PI
|
||||
|
||||
class Sphere(parent: VisualObject?, var radius: Number) : VisualLeaf3D(parent) {
|
||||
var phiStart by number(0.0)
|
||||
var phi by number(2 * PI)
|
||||
var thetaStart by number(0.0)
|
||||
var theta by number(PI)
|
||||
}
|
||||
class Sphere(
|
||||
var radius: Float,
|
||||
var phiStart: Float = 0f,
|
||||
var phi: Float = PI2,
|
||||
var thetaStart: Float = 0f,
|
||||
var theta: Float = PI.toFloat()
|
||||
) : VisualLeaf3D()
|
||||
|
||||
fun VisualGroup3D.sphere(
|
||||
inline fun VisualGroup3D.sphere(
|
||||
radius: Number,
|
||||
phi: Number = 2 * PI,
|
||||
theta: Number = PI,
|
||||
name: String? = null,
|
||||
action: Sphere.() -> Unit = {}
|
||||
) = Sphere(this, radius).apply(action).apply {
|
||||
this.phi = phi.toDouble()
|
||||
this.theta = theta.toDouble()
|
||||
}.also { set(name, it) }
|
||||
) = Sphere(
|
||||
radius.toFloat(),
|
||||
phi = phi.toFloat(),
|
||||
theta = theta.toFloat()
|
||||
).apply(action).also { set(name, it) }
|
@ -1,21 +1,19 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.vis.common.VisualObject
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
/**
|
||||
* Stright tube segment
|
||||
* Straight tube segment
|
||||
*/
|
||||
class Tube(
|
||||
parent: VisualObject?,
|
||||
var radius: Float,
|
||||
var height: Float,
|
||||
var innerRadius: Float = 0f,
|
||||
var startAngle: Float = 0f,
|
||||
var angle: Float = PI2
|
||||
) : VisualLeaf3D(parent), Shape {
|
||||
) : VisualLeaf3D(), Shape {
|
||||
|
||||
init {
|
||||
require(radius > 0)
|
||||
@ -108,7 +106,7 @@ class Tube(
|
||||
}
|
||||
}
|
||||
|
||||
fun VisualGroup3D.tube(
|
||||
inline fun VisualGroup3D.tube(
|
||||
r: Number,
|
||||
height: Number,
|
||||
innerRadius: Number = 0f,
|
||||
@ -116,16 +114,12 @@ fun VisualGroup3D.tube(
|
||||
angle: Number = 2 * PI,
|
||||
name: String? = null,
|
||||
block: Tube.() -> Unit = {}
|
||||
): Tube {
|
||||
val tube = Tube(
|
||||
this,
|
||||
r.toFloat(),
|
||||
height.toFloat(),
|
||||
innerRadius.toFloat(),
|
||||
startAngle.toFloat(),
|
||||
angle.toFloat()
|
||||
).apply(
|
||||
block
|
||||
)
|
||||
return tube.also { set(name, it) }
|
||||
}
|
||||
): Tube = Tube(
|
||||
r.toFloat(),
|
||||
height.toFloat(),
|
||||
innerRadius.toFloat(),
|
||||
startAngle.toFloat(),
|
||||
angle.toFloat()
|
||||
).apply(
|
||||
block
|
||||
).also { set(name, it) }
|
@ -0,0 +1,40 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.context.AbstractPlugin
|
||||
import hep.dataforge.context.PluginFactory
|
||||
import hep.dataforge.context.PluginTag
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.vis.common.VisualPlugin
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class Visual3DPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
override fun provideTop(target: String): Map<Name, Any> {
|
||||
return if (target == VisualPlugin.VISUAL_FACTORY_TYPE) {
|
||||
mapOf()
|
||||
} else {
|
||||
emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
companion object : PluginFactory<Visual3DPlugin> {
|
||||
override val tag: PluginTag = PluginTag(name = "visual.spatial", group = PluginTag.DATAFORGE_GROUP)
|
||||
override val type: KClass<out Visual3DPlugin> = Visual3DPlugin::class
|
||||
override fun invoke(meta: Meta): Visual3DPlugin = Visual3DPlugin(meta)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun VisualObject3D.update(meta: Meta) {
|
||||
fun Meta.toVector(default: Float = 0f) = Value3(
|
||||
this[VisualObject3D.x].float ?: default,
|
||||
this[VisualObject3D.y].float ?: default,
|
||||
this[VisualObject3D.z].float ?: default
|
||||
)
|
||||
|
||||
meta[VisualObject3D.position].node?.toVector()?.let { position = it }
|
||||
meta[VisualObject3D.rotation].node?.toVector()?.let { rotation = it }
|
||||
meta[VisualObject3D.scale].node?.toVector(1f)?.let { scale = it }
|
||||
meta["properties"].node?.let { configure(it) }
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.output.Output
|
||||
import hep.dataforge.vis.common.AbstractVisualObject
|
||||
@ -61,18 +62,29 @@ interface VisualObject3D : VisualObject {
|
||||
}
|
||||
}
|
||||
|
||||
abstract class VisualLeaf3D(parent: VisualObject?) : AbstractVisualObject(parent), VisualObject3D, Configurable {
|
||||
abstract class VisualLeaf3D : AbstractVisualObject(), VisualObject3D, Configurable {
|
||||
override var position: Value3 = Value3()
|
||||
override var rotation: Value3 = Value3()
|
||||
override var scale: Value3 = Value3(1f, 1f, 1f)
|
||||
}
|
||||
|
||||
class VisualGroup3D(parent: VisualObject? = null) : VisualGroup<VisualObject3D>(parent), VisualObject3D, Configurable {
|
||||
class VisualGroup3D : VisualGroup<VisualObject3D>(), VisualObject3D, Configurable {
|
||||
|
||||
override var position: Value3 = Value3()
|
||||
override var rotation: Value3 = Value3()
|
||||
override var scale: Value3 = Value3(1f, 1f, 1f)
|
||||
|
||||
/**
|
||||
* A container for templates visible inside this group
|
||||
*/
|
||||
var templates: VisualGroup3D? = null
|
||||
set(value) {
|
||||
value?.parent = this
|
||||
field = value
|
||||
}
|
||||
|
||||
fun getTemplate(name: Name): VisualObject3D? = templates?.get(name) ?: (parent as? VisualGroup3D)?.getTemplate(name)
|
||||
|
||||
override fun MetaBuilder.updateMeta() {
|
||||
updatePosition()
|
||||
updateChildren()
|
||||
@ -80,7 +92,7 @@ class VisualGroup3D(parent: VisualObject? = null) : VisualGroup<VisualObject3D>(
|
||||
}
|
||||
|
||||
fun VisualGroup3D.group(key: String? = null, action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
|
||||
VisualGroup3D(this).apply(action).also { set(key, it) }
|
||||
VisualGroup3D().apply(action).also { set(key, it) }
|
||||
|
||||
fun Output<VisualObject3D>.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) =
|
||||
render(VisualGroup3D().apply(action), meta)
|
||||
@ -108,7 +120,7 @@ var VisualObject3D.rotationOrder: RotationOrder
|
||||
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default. Not inherited
|
||||
*/
|
||||
var VisualObject3D.detail: Int?
|
||||
get() = getProperty(DETAIL_KEY,false).int
|
||||
get() = getProperty(DETAIL_KEY, false).int
|
||||
set(value) = setProperty(DETAIL_KEY, value)
|
||||
|
||||
var VisualObject3D.material: Meta?
|
||||
|
@ -10,7 +10,7 @@ import kotlin.test.assertEquals
|
||||
class ConvexTest {
|
||||
@Test
|
||||
fun testConvexBuilder() {
|
||||
val group = VisualNode().apply {
|
||||
val group = VisualGroup3D().apply {
|
||||
convex {
|
||||
point(50, 50, -50)
|
||||
point(50, -50, -50)
|
||||
@ -25,7 +25,7 @@ class ConvexTest {
|
||||
|
||||
val convex = group.first() as Convex
|
||||
|
||||
val pointsNode = convex.config["points"].node
|
||||
val pointsNode = convex.toMeta()["points"].node
|
||||
|
||||
assertEquals(8, pointsNode?.items?.count())
|
||||
val points = pointsNode?.getAll("point".toName())
|
||||
|
@ -1,7 +1,6 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.vis.common.Colors
|
||||
import hep.dataforge.vis.common.color
|
||||
import kotlin.math.PI
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -9,7 +8,7 @@ import kotlin.test.assertEquals
|
||||
class GroupTest {
|
||||
@Test
|
||||
fun testGroupWithComposite(){
|
||||
val group = VisualNode().apply{
|
||||
val group = VisualGroup3D().apply{
|
||||
union {
|
||||
box(100, 100, 100) {
|
||||
z = 100
|
||||
@ -30,7 +29,7 @@ class GroupTest {
|
||||
}
|
||||
box(100, 100, 100)
|
||||
y = 300
|
||||
material(Colors.red)
|
||||
color(Colors.red)
|
||||
}
|
||||
subtract{
|
||||
box(100, 100, 100) {
|
||||
@ -40,7 +39,7 @@ class GroupTest {
|
||||
}
|
||||
box(100, 100, 100)
|
||||
y = -300
|
||||
material(Colors.blue)
|
||||
color(Colors.blue)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,18 @@
|
||||
package hep.dataforge.vis.spatial
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class SerializationTest {
|
||||
@Test
|
||||
fun testCubeSerialization(){
|
||||
val cube = Box(null,100f,100f,100f).apply{
|
||||
color(222)
|
||||
}
|
||||
val meta = cube.toMeta()
|
||||
println(meta)
|
||||
val newCube = Box(Global,null, meta)
|
||||
assertEquals(cube,newCube)
|
||||
}
|
||||
}
|
@ -37,7 +37,8 @@ include(
|
||||
":dataforge-vis-spatial-fx",
|
||||
":dataforge-vis-spatial-js",
|
||||
// ":dataforge-vis-jsroot",
|
||||
":dataforge-vis-spatial-gdml"
|
||||
":dataforge-vis-spatial-gdml",
|
||||
":spatial-js-demo"
|
||||
)
|
||||
|
||||
//if(file("../dataforge-core").exists()) {
|
||||
|
19
spatial-js-demo/build.gradle.kts
Normal file
19
spatial-js-demo/build.gradle.kts
Normal file
@ -0,0 +1,19 @@
|
||||
plugins {
|
||||
id("scientifik.js")
|
||||
//id("kotlin-dce-js")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":dataforge-vis-spatial-js"))
|
||||
api("info.laht.threekt:threejs-wrapper:0.106-npm-3")
|
||||
testCompile(kotlin("test-js"))
|
||||
}
|
||||
|
||||
//kotlin{
|
||||
// sourceSets["main"].dependencies{
|
||||
// implementation(npm("three","0.106.2"))
|
||||
// implementation(npm("@hi-level/three-csg"))
|
||||
// implementation(npm("style-loader"))
|
||||
// implementation(npm("element-resize-event"))
|
||||
// }
|
||||
//}
|
Loading…
Reference in New Issue
Block a user