forked from kscience/visionforge
GDML demo renders something
This commit is contained in:
parent
687393c243
commit
d3500c3a57
@ -4,6 +4,7 @@ import hep.dataforge.meta.Meta
|
|||||||
import hep.dataforge.meta.MetaBuilder
|
import hep.dataforge.meta.MetaBuilder
|
||||||
import hep.dataforge.meta.buildMeta
|
import hep.dataforge.meta.buildMeta
|
||||||
import hep.dataforge.meta.set
|
import hep.dataforge.meta.set
|
||||||
|
import hep.dataforge.names.toName
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Taken from https://github.com/markaren/three.kt/blob/master/threejs-wrapper/src/main/kotlin/info/laht/threekt/math/ColorConstants.kt
|
* Taken from https://github.com/markaren/three.kt/blob/master/threejs-wrapper/src/main/kotlin/info/laht/threekt/math/ColorConstants.kt
|
||||||
@ -181,13 +182,14 @@ object Colors {
|
|||||||
const val yellowgreen = 0x9ACD32
|
const val yellowgreen = 0x9ACD32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val material = "material".toName()
|
||||||
|
|
||||||
fun VisualObject.color(rgb: Int) {
|
fun VisualObject.color(rgb: Int) {
|
||||||
this.properties["material"] = rgb
|
this.config[material] = rgb
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualObject.color(meta: Meta) {
|
fun VisualObject.color(meta: Meta) {
|
||||||
this.properties["material"] = meta
|
this.config[material] = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualObject.color(builder: MetaBuilder.() -> Unit) {
|
fun VisualObject.color(builder: MetaBuilder.() -> Unit) {
|
||||||
|
@ -1,29 +1,41 @@
|
|||||||
package hep.dataforge.vis.common
|
package hep.dataforge.vis.common
|
||||||
|
|
||||||
import hep.dataforge.meta.EmptyMeta
|
import hep.dataforge.meta.Config
|
||||||
|
import hep.dataforge.meta.Laminate
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.Styled
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import hep.dataforge.provider.Provider
|
import hep.dataforge.provider.Provider
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.collections.HashSet
|
||||||
|
import kotlin.collections.Iterable
|
||||||
|
import kotlin.collections.Iterator
|
||||||
|
import kotlin.collections.Map
|
||||||
|
import kotlin.collections.emptyMap
|
||||||
|
import kotlin.collections.forEach
|
||||||
|
import kotlin.collections.plus
|
||||||
|
import kotlin.collections.removeAll
|
||||||
|
import kotlin.collections.set
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A display group which allows both named and unnamed children
|
* A display group which allows both named and unnamed children
|
||||||
*/
|
*/
|
||||||
class VisualGroup(
|
class VisualGroup(
|
||||||
override val parent: VisualObject? = null, meta: Meta = EmptyMeta
|
override val parent: VisualObject? = null, tagRefs: Array<out Meta> = emptyArray()
|
||||||
) : VisualObject, Iterable<VisualObject>, Provider {
|
) : VisualObject, Iterable<VisualObject>, Provider {
|
||||||
|
|
||||||
private val namedChildren = HashMap<Name, VisualObject>()
|
private val namedChildren = HashMap<Name, VisualObject>()
|
||||||
private val unnamedChildren = ArrayList<VisualObject>()
|
private val unnamedChildren = ArrayList<VisualObject>()
|
||||||
|
|
||||||
override val defaultTarget: String get() = VisualObject.TYPE
|
override val defaultTarget: String get() = VisualObject.TYPE
|
||||||
override val properties: Styled = Styled(meta)
|
override val config = Config()
|
||||||
|
|
||||||
|
override val properties: Laminate by lazy { combineProperties(parent, config, tagRefs) }
|
||||||
|
|
||||||
override fun iterator(): Iterator<VisualObject> = (namedChildren.values + unnamedChildren).iterator()
|
override fun iterator(): Iterator<VisualObject> = (namedChildren.values + unnamedChildren).iterator()
|
||||||
|
|
||||||
override fun provideTop(target: String): Map<Name, Any> {
|
override fun provideTop(target: String): Map<Name, Any> {
|
||||||
return when(target){
|
return when (target) {
|
||||||
VisualObject.TYPE -> namedChildren
|
VisualObject.TYPE -> namedChildren
|
||||||
else -> emptyMap()
|
else -> emptyMap()
|
||||||
}
|
}
|
||||||
@ -49,22 +61,26 @@ class VisualGroup(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 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(key: String?, child: VisualObject?) {
|
operator fun set(name: Name?, child: VisualObject?) {
|
||||||
if(key == null){
|
when {
|
||||||
|
name != null -> {
|
||||||
} else {
|
if (child == null) {
|
||||||
val name = key.toName()
|
namedChildren.remove(name)
|
||||||
if (child == null) {
|
} else {
|
||||||
namedChildren.remove(name)
|
namedChildren[name] = child
|
||||||
} else {
|
}
|
||||||
namedChildren[name] = child
|
listeners.forEach { it.callback(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: VisualObject?) = set(key?.asName(), child)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append unnamed child
|
* Append unnamed child
|
||||||
*/
|
*/
|
||||||
|
@ -2,24 +2,34 @@ package hep.dataforge.vis.common
|
|||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import hep.dataforge.provider.Type
|
import hep.dataforge.provider.Type
|
||||||
import hep.dataforge.vis.common.VisualObject.Companion.META_KEY
|
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.TAGS_KEY
|
||||||
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
|
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
|
||||||
|
|
||||||
|
private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
||||||
|
private fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A root type for display hierarchy
|
* A root type for display hierarchy
|
||||||
*/
|
*/
|
||||||
@Type(TYPE)
|
@Type(TYPE)
|
||||||
interface VisualObject : MetaRepr {
|
interface VisualObject : MetaRepr, Configurable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parent object of this one. If null, this one is a root.
|
* The parent object of this one. If null, this one is a root.
|
||||||
*/
|
*/
|
||||||
val parent: VisualObject?
|
val parent: VisualObject?
|
||||||
|
|
||||||
val properties: Styled
|
/**
|
||||||
|
* Individual properties configurator
|
||||||
|
*/
|
||||||
|
override val config: Config
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All properties including inherited ones
|
||||||
|
*/
|
||||||
|
val properties: Laminate
|
||||||
|
|
||||||
override fun toMeta(): Meta = buildMeta {
|
override fun toMeta(): Meta = buildMeta {
|
||||||
"type" to this::class
|
"type" to this::class
|
||||||
@ -37,18 +47,11 @@ interface VisualObject : MetaRepr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the property of this display object of parent's if not found
|
|
||||||
*/
|
|
||||||
tailrec fun VisualObject.getProperty(name: Name): MetaItem<*>? = properties[name] ?: parent?.getProperty(name)
|
|
||||||
|
|
||||||
fun VisualObject.getProperty(name: String): MetaItem<*>? = getProperty(name.toName())
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A change listener for [VisualObject] configuration.
|
* A change listener for [VisualObject] configuration.
|
||||||
*/
|
*/
|
||||||
fun VisualObject.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)
|
config.onChange(owner, action)
|
||||||
parent?.onChange(owner, action)
|
parent?.onChange(owner, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +59,7 @@ fun VisualObject.onChange(owner: Any?, action: (Name, before: MetaItem<*>?, afte
|
|||||||
* Remove all meta listeners with matching owners
|
* Remove all meta listeners with matching owners
|
||||||
*/
|
*/
|
||||||
fun VisualObject.removeChangeListener(owner: Any?) {
|
fun VisualObject.removeChangeListener(owner: Any?) {
|
||||||
properties.removeListener(owner)
|
config.removeListener(owner)
|
||||||
parent?.removeChangeListener(owner)
|
parent?.removeChangeListener(owner)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,18 +67,28 @@ fun VisualObject.removeChangeListener(owner: Any?) {
|
|||||||
/**
|
/**
|
||||||
* Additional meta not relevant to display
|
* Additional meta not relevant to display
|
||||||
*/
|
*/
|
||||||
val VisualObject.meta: Meta get() = properties[META_KEY]?.node ?: EmptyMeta
|
val VisualObject.meta: Meta get() = config[META_KEY]?.node ?: EmptyMeta
|
||||||
|
|
||||||
val VisualObject.tags: List<String> get() = properties[TAGS_KEY].stringList
|
val VisualObject.tags: List<String> get() = config[TAGS_KEY].stringList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic [VisualObject] leaf element
|
* Basic [VisualObject] leaf element
|
||||||
*/
|
*/
|
||||||
open class DisplayLeaf(
|
open class VisualLeaf(
|
||||||
override val parent: VisualObject?,
|
final override val parent: VisualObject?,
|
||||||
meta: Meta = EmptyMeta
|
tagRefs: Array<out Meta>
|
||||||
) : VisualObject {
|
) : VisualObject {
|
||||||
final override val properties = Styled(meta)
|
final override val config = Config()
|
||||||
|
|
||||||
|
override val properties: Laminate by lazy { combineProperties(parent, config, tagRefs) }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun combineProperties(parent: VisualObject?, config: Config, tagRefs: Array<out Meta>): Laminate {
|
||||||
|
val list = ArrayList<Meta>(tagRefs.size + 2)
|
||||||
|
list += config
|
||||||
|
list.addAll(tagRefs)
|
||||||
|
parent?.properties?.let { list.add(it) }
|
||||||
|
return Laminate(list)
|
||||||
}
|
}
|
||||||
|
|
||||||
///**
|
///**
|
||||||
|
@ -2,13 +2,16 @@ package hep.dataforge.vis.common
|
|||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.names.asName
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
fun String.asName() = NameToken(this).asName()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A delegate for display object properties
|
* A delegate for display object properties
|
||||||
*/
|
*/
|
||||||
@ -18,17 +21,17 @@ class DisplayObjectDelegate(
|
|||||||
val inherited: Boolean
|
val inherited: Boolean
|
||||||
) : ReadWriteProperty<VisualObject, MetaItem<*>?> {
|
) : ReadWriteProperty<VisualObject, MetaItem<*>?> {
|
||||||
override fun getValue(thisRef: VisualObject, property: KProperty<*>): MetaItem<*>? {
|
override fun getValue(thisRef: VisualObject, property: KProperty<*>): MetaItem<*>? {
|
||||||
val name = key ?: property.name.toName()
|
val name = key ?: property.name.asName()
|
||||||
return if (inherited) {
|
return if (inherited) {
|
||||||
thisRef.getProperty(name)
|
|
||||||
} else {
|
|
||||||
thisRef.properties[name]
|
thisRef.properties[name]
|
||||||
|
} else {
|
||||||
|
thisRef.config[name]
|
||||||
} ?: default
|
} ?: default
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: VisualObject, property: KProperty<*>, value: MetaItem<*>?) {
|
override fun setValue(thisRef: VisualObject, property: KProperty<*>, value: MetaItem<*>?) {
|
||||||
val name = key ?: property.name.toName()
|
val name = key ?: property.name.asName()
|
||||||
thisRef.properties[name] = value
|
thisRef.config[name] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,70 +46,71 @@ class DisplayObjectDelegateWrapper<T>(
|
|||||||
//private var cachedName: Name? = null
|
//private var cachedName: Name? = null
|
||||||
|
|
||||||
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
||||||
val name = key ?: property.name.toName()
|
val name = key ?: property.name.asName()
|
||||||
return if (inherited) {
|
return if (inherited) {
|
||||||
read(thisRef.getProperty(name))
|
|
||||||
} else {
|
|
||||||
read(thisRef.properties[name])
|
read(thisRef.properties[name])
|
||||||
|
} else {
|
||||||
|
read(thisRef.config[name])
|
||||||
} ?: default
|
} ?: default
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: VisualObject, property: KProperty<*>, value: T) {
|
override fun setValue(thisRef: VisualObject, property: KProperty<*>, value: T) {
|
||||||
val name = key ?: property.name.toName()
|
val name = key ?: property.name.asName()
|
||||||
thisRef.properties[name] = value
|
thisRef.config[name] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun VisualObject.value(default: Value? = null, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.value(default: Value? = null, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.value }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.value }
|
||||||
|
|
||||||
fun VisualObject.string(default: String? = null, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.string(default: String? = null, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.string }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.string }
|
||||||
|
|
||||||
fun VisualObject.boolean(default: Boolean? = null, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.boolean(default: Boolean? = null, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.boolean }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.boolean }
|
||||||
|
|
||||||
fun VisualObject.number(default: Number? = null, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.number(default: Number? = null, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.number }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.number }
|
||||||
|
|
||||||
fun VisualObject.double(default: Double? = null, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.double(default: Double? = null, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.double }
|
||||||
|
|
||||||
fun VisualObject.int(default: Int? = null, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.int(default: Int? = null, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.int }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.int }
|
||||||
|
|
||||||
|
|
||||||
fun VisualObject.node(key: String? = null, inherited: Boolean = true) =
|
fun VisualObject.node(key: String? = null, inherited: Boolean = true) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it.node }
|
DisplayObjectDelegateWrapper(key?.asName(), null, inherited) { it.node }
|
||||||
|
|
||||||
fun VisualObject.item(key: String? = null, inherited: Boolean = true) =
|
fun VisualObject.item(key: String? = null, inherited: Boolean = true) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), null, inherited) { it }
|
DisplayObjectDelegateWrapper(key?.asName(), null, inherited) { it }
|
||||||
|
|
||||||
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
|
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
|
||||||
|
|
||||||
@JvmName("safeString")
|
@JvmName("safeString")
|
||||||
fun VisualObject.string(default: String, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.string(default: String, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.string }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.string }
|
||||||
|
|
||||||
@JvmName("safeBoolean")
|
@JvmName("safeBoolean")
|
||||||
fun VisualObject.boolean(default: Boolean, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.boolean(default: Boolean, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.boolean }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.boolean }
|
||||||
|
|
||||||
@JvmName("safeNumber")
|
@JvmName("safeNumber")
|
||||||
fun VisualObject.number(default: Number, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.number(default: Number, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.number }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.number }
|
||||||
|
|
||||||
@JvmName("safeDouble")
|
@JvmName("safeDouble")
|
||||||
fun VisualObject.double(default: Double, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.double(default: Double, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.double }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.double }
|
||||||
|
|
||||||
@JvmName("safeInt")
|
@JvmName("safeInt")
|
||||||
fun VisualObject.int(default: Int, key: String? = null, inherited: Boolean = false) =
|
fun VisualObject.int(default: Int, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { it.int }
|
DisplayObjectDelegateWrapper(key?.asName(), default, inherited) { it.int }
|
||||||
|
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> VisualObject.enum(default: E, key: String? = null, inherited: Boolean = false) =
|
inline fun <reified E : Enum<E>> VisualObject.enum(default: E, key: String? = null, inherited: Boolean = false) =
|
||||||
DisplayObjectDelegateWrapper(key?.toName(), default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
|
DisplayObjectDelegateWrapper(key?.let{ NameToken(it).asName()}, default, inherited) { item -> item.string?.let { enumValueOf<E>(it) } }
|
||||||
|
|
||||||
//merge properties
|
//merge properties
|
||||||
|
|
||||||
@ -116,11 +120,11 @@ fun <T> VisualObject.merge(
|
|||||||
): ReadOnlyProperty<VisualObject, T> {
|
): ReadOnlyProperty<VisualObject, T> {
|
||||||
return object : ReadOnlyProperty<VisualObject, T> {
|
return object : ReadOnlyProperty<VisualObject, T> {
|
||||||
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
||||||
val name = key?.toName() ?: property.name.toName()
|
val name = key?.asName() ?: property.name.asName()
|
||||||
val sequence = sequence<MetaItem<*>> {
|
val sequence = sequence<MetaItem<*>> {
|
||||||
var thisObj: VisualObject? = thisRef
|
var thisObj: VisualObject? = thisRef
|
||||||
while (thisObj != null) {
|
while (thisObj != null) {
|
||||||
thisObj.properties[name]?.let { yield(it) }
|
thisObj.config[name]?.let { yield(it) }
|
||||||
thisObj = thisObj.parent
|
thisObj = thisObj.parent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import hep.dataforge.meta.*
|
|||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.getProperty
|
|
||||||
import hep.dataforge.vis.common.onChange
|
import hep.dataforge.vis.common.onChange
|
||||||
import javafx.beans.binding.ObjectBinding
|
import javafx.beans.binding.ObjectBinding
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
@ -24,7 +23,7 @@ class DisplayObjectFXListener(val obj: VisualObject) {
|
|||||||
operator fun get(key: Name): ObjectBinding<MetaItem<*>?> {
|
operator fun get(key: Name): ObjectBinding<MetaItem<*>?> {
|
||||||
return binndings.getOrPut(key) {
|
return binndings.getOrPut(key) {
|
||||||
object : ObjectBinding<MetaItem<*>?>() {
|
object : ObjectBinding<MetaItem<*>?>() {
|
||||||
override fun computeValue(): MetaItem<*>? = obj.getProperty(key)
|
override fun computeValue(): MetaItem<*>? = obj.properties[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,21 +27,14 @@ class RendererDemoView : View() {
|
|||||||
|
|
||||||
renderer.render {
|
renderer.render {
|
||||||
group = group {
|
group = group {
|
||||||
box {
|
box(100,100,100)
|
||||||
xSize = 100.0
|
box(100,100,100) {
|
||||||
ySize = 100.0
|
|
||||||
zSize = 100.0
|
|
||||||
}
|
|
||||||
box {
|
|
||||||
x = 110.0
|
x = 110.0
|
||||||
xSize = 100.0
|
|
||||||
ySize = 100.0
|
|
||||||
zSize = 100.0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var color by group.properties.number(1530).int
|
var color by group.config.number(1530).int
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
val random = Random(111)
|
val random = Random(111)
|
||||||
|
@ -11,28 +11,57 @@ import kotlin.math.cos
|
|||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
|
||||||
private fun VisualObject.applyPosition(pos: GDMLPosition): VisualObject = apply {
|
private fun VisualObject.withPosition(
|
||||||
x = pos.x
|
pos: GDMLPosition? = null,
|
||||||
y = pos.y
|
rotation: GDMLRotation? = null,
|
||||||
z = pos.z
|
scale: GDMLScale? = null
|
||||||
//TODO convert units if needed
|
): VisualObject =
|
||||||
}
|
apply {
|
||||||
|
// if( this is VisualObject3D){
|
||||||
|
// pos?.let {
|
||||||
|
// x = pos.x
|
||||||
|
// y = pos.y
|
||||||
|
// z = pos.z
|
||||||
|
// }
|
||||||
|
// rotation?.let {
|
||||||
|
// rotationX = rotation.x
|
||||||
|
// rotationY = rotation.y
|
||||||
|
// rotationZ = rotation.z
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
pos?.let {
|
||||||
|
x = pos.x
|
||||||
|
y = pos.y
|
||||||
|
z = pos.z
|
||||||
|
}
|
||||||
|
rotation?.let {
|
||||||
|
rotationX = rotation.x
|
||||||
|
rotationY = rotation.y
|
||||||
|
rotationZ = rotation.z
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
scale?.let {
|
||||||
|
scaleX = scale.x
|
||||||
|
scaleY = scale.y
|
||||||
|
scaleZ = scale.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 {
|
private fun VisualGroup.addSolid(
|
||||||
|
root: GDML,
|
||||||
|
solid: GDMLSolid,
|
||||||
|
name: String? = null,
|
||||||
|
block: VisualObject.() -> Unit = {}
|
||||||
|
): VisualObject {
|
||||||
return when (solid) {
|
return when (solid) {
|
||||||
is GDMLBox -> box(solid.x, solid.y, solid.z)
|
is GDMLBox -> box(solid.x, solid.y, solid.z, name)
|
||||||
is GDMLTube -> cylinder(solid.rmax, solid.z) {
|
is GDMLTube -> cylinder(solid.rmax, solid.z, name) {
|
||||||
startAngle = solid.startphi
|
startAngle = solid.startphi
|
||||||
angle = solid.deltaphi
|
angle = solid.deltaphi
|
||||||
}
|
}
|
||||||
is GDMLXtru -> extrude {
|
is GDMLXtru -> extrude(name) {
|
||||||
shape {
|
shape {
|
||||||
solid.vertices.forEach {
|
solid.vertices.forEach {
|
||||||
point(it.x, it.y)
|
point(it.x, it.y)
|
||||||
@ -46,6 +75,7 @@ private fun VisualGroup.addSolid(root: GDML, solid: GDMLSolid, block: VisualObje
|
|||||||
//Add solid with modified scale
|
//Add solid with modified scale
|
||||||
val innerSolid = solid.solidref.resolve(root)
|
val innerSolid = solid.solidref.resolve(root)
|
||||||
?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined")
|
?: error("Solid with tag ${solid.solidref.ref} for scaled solid ${solid.name} not defined")
|
||||||
|
|
||||||
addSolid(root, innerSolid) {
|
addSolid(root, innerSolid) {
|
||||||
block()
|
block()
|
||||||
scaleX = scaleX.toDouble() * solid.scale.x.toDouble()
|
scaleX = scaleX.toDouble() * solid.scale.x.toDouble()
|
||||||
@ -53,12 +83,12 @@ private fun VisualGroup.addSolid(root: GDML, solid: GDMLSolid, block: VisualObje
|
|||||||
scaleZ = scaleZ.toDouble() * solid.scale.z.toDouble()
|
scaleZ = scaleZ.toDouble() * solid.scale.z.toDouble()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is GDMLSphere -> sphere(solid.rmax, solid.deltaphi, solid.deltatheta) {
|
is GDMLSphere -> sphere(solid.rmax, solid.deltaphi, solid.deltatheta, name) {
|
||||||
phiStart = solid.startphi.toDouble()
|
phiStart = solid.startphi.toDouble()
|
||||||
thetaStart = solid.starttheta.toDouble()
|
thetaStart = solid.starttheta.toDouble()
|
||||||
}
|
}
|
||||||
is GDMLOrb -> sphere(solid.r)
|
is GDMLOrb -> sphere(solid.r, name = name)
|
||||||
is GDMLPolyhedra -> extrude {
|
is GDMLPolyhedra -> extrude(name) {
|
||||||
//getting the radius of first
|
//getting the radius of first
|
||||||
require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" }
|
require(solid.planes.size > 1) { "The polyhedron geometry requires at least two planes" }
|
||||||
val baseRadius = solid.planes.first().rmax.toDouble()
|
val baseRadius = solid.planes.first().rmax.toDouble()
|
||||||
@ -81,14 +111,13 @@ private fun VisualGroup.addSolid(root: GDML, solid: GDMLSolid, block: VisualObje
|
|||||||
is GDMLSubtraction -> CompositeType.SUBTRACT
|
is GDMLSubtraction -> CompositeType.SUBTRACT
|
||||||
is GDMLIntersection -> CompositeType.INTERSECT
|
is GDMLIntersection -> CompositeType.INTERSECT
|
||||||
}
|
}
|
||||||
return composite(type) {
|
|
||||||
|
return composite(type, name) {
|
||||||
addSolid(root, first) {
|
addSolid(root, first) {
|
||||||
solid.resolveFirstPosition(root)?.let { applyPosition(it) }
|
withPosition(solid.resolveFirstPosition(root), solid.resolveFirstRotation(root), null)
|
||||||
solid.resolveFirstRotation(root)?.let { applyRotation(it) }
|
|
||||||
}
|
}
|
||||||
addSolid(root, second)
|
addSolid(root, second)
|
||||||
solid.resolvePosition(root)?.let { applyPosition(it) }
|
withPosition(solid.resolvePosition(root), solid.resolveRotation(root), null)
|
||||||
solid.resolveRotation(root)?.let { applyRotation(it) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.apply(block)
|
}.apply(block)
|
||||||
@ -97,30 +126,42 @@ private fun VisualGroup.addSolid(root: GDML, solid: GDMLSolid, block: VisualObje
|
|||||||
private fun VisualGroup.addVolume(
|
private fun VisualGroup.addVolume(
|
||||||
root: GDML,
|
root: GDML,
|
||||||
group: GDMLGroup,
|
group: GDMLGroup,
|
||||||
|
position: GDMLPosition? = null,
|
||||||
|
rotation: GDMLRotation? = null,
|
||||||
|
scale: GDMLScale? = null,
|
||||||
resolveColor: GDMLMaterial.() -> Meta
|
resolveColor: GDMLMaterial.() -> Meta
|
||||||
): VisualGroup {
|
) {
|
||||||
if (group is GDMLVolume) {
|
|
||||||
val solid = group.solidref.resolve(root)
|
|
||||||
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
|
|
||||||
val material = group.materialref.resolve(root)
|
|
||||||
?: error("Material with tag ${group.materialref.ref} for volume ${group.name} not defined")
|
|
||||||
|
|
||||||
addSolid(root, solid) {
|
group(group.name) {
|
||||||
color(material.resolveColor())
|
withPosition(position, rotation, scale)
|
||||||
|
|
||||||
|
if (group is GDMLVolume) {
|
||||||
|
val solid = group.solidref.resolve(root)
|
||||||
|
?: error("Solid with tag ${group.solidref.ref} for volume ${group.name} not defined")
|
||||||
|
val material = group.materialref.resolve(root)
|
||||||
|
?: error("Material with tag ${group.materialref.ref} for volume ${group.name} not defined")
|
||||||
|
|
||||||
|
addSolid(root, solid, solid.name) {
|
||||||
|
color(material.resolveColor())
|
||||||
|
}
|
||||||
|
//TODO render placements
|
||||||
}
|
}
|
||||||
//TODO render placements
|
|
||||||
}
|
|
||||||
|
|
||||||
group.physVolumes.forEach {
|
group.physVolumes.forEach { physVolume ->
|
||||||
val volume: GDMLGroup =
|
val volume: GDMLGroup = physVolume.volumeref.resolve(root)
|
||||||
it.volumeref.resolve(root) ?: error("Volume with ref ${it.volumeref.ref} could not be resolved")
|
?: error("Volume with ref ${physVolume.volumeref.ref} could not be resolved")
|
||||||
addVolume(root, volume, resolveColor).apply {
|
|
||||||
it.resolvePosition(root)?.let { pos -> applyPosition(pos) }
|
addVolume(
|
||||||
it.resolveRotation(root)?.let { rot -> applyRotation(rot) }
|
root,
|
||||||
|
volume,
|
||||||
|
physVolume.resolvePosition(root),
|
||||||
|
physVolume.resolveRotation(root),
|
||||||
|
physVolume.resolveScale(root),
|
||||||
|
resolveColor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ import scientifik.gdml.GDML
|
|||||||
import kotlin.browser.document
|
import kotlin.browser.document
|
||||||
import kotlin.dom.clear
|
import kotlin.dom.clear
|
||||||
|
|
||||||
class GDMLDemoApp : ApplicationBase() {
|
private class GDMLDemoApp : ApplicationBase() {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,13 +56,13 @@ class GDMLDemoApp : ApplicationBase() {
|
|||||||
|
|
||||||
val context = Global.context("demo") {}
|
val context = Global.context("demo") {}
|
||||||
val three = context.plugins.load(ThreePlugin)
|
val three = context.plugins.load(ThreePlugin)
|
||||||
val canvas = document.getElementById("canvas") ?: error("Element with id canvas not found on page")
|
|
||||||
canvas.clear()
|
|
||||||
val output = three.output(canvas)
|
|
||||||
//val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
//val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
||||||
|
|
||||||
|
val canvas = document.getElementById("canvas") ?: error("Element with id canvas not found on page")
|
||||||
|
|
||||||
val action: suspend (String) -> Unit = {
|
val action: suspend (String) -> Unit = {
|
||||||
|
canvas.clear()
|
||||||
|
val output = three.output(canvas)
|
||||||
val gdml = GDML.format.parse(GDML.serializer(), it)
|
val gdml = GDML.format.parse(GDML.serializer(), it)
|
||||||
val visual = gdml.toVisual()
|
val visual = gdml.toVisual()
|
||||||
output.render(visual)
|
output.render(visual)
|
||||||
|
@ -13,7 +13,7 @@ class BMNTest {
|
|||||||
|
|
||||||
val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO")
|
||||||
val file = File("D:\\Work\\Projects\\gdml.kt\\src\\commonTest\\resources\\gdml\\geofile_full.xml")
|
val file = File("D:\\Work\\Projects\\gdml.kt\\src\\commonTest\\resources\\gdml\\geofile_full.xml")
|
||||||
val stream = if(file.exists()){
|
val stream = if (file.exists()) {
|
||||||
file.inputStream()
|
file.inputStream()
|
||||||
} else {
|
} else {
|
||||||
url.openStream()
|
url.openStream()
|
||||||
@ -21,7 +21,7 @@ class BMNTest {
|
|||||||
|
|
||||||
val xmlReader = StAXReader(stream, "UTF-8")
|
val xmlReader = StAXReader(stream, "UTF-8")
|
||||||
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||||
repeat(5) {
|
repeat(20) {
|
||||||
xml.toVisual()
|
xml.toVisual()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import kotlin.math.sin
|
|||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
class ThreeDemoApp : ApplicationBase() {
|
private class ThreeDemoApp : ApplicationBase() {
|
||||||
|
|
||||||
override val stateKeys: List<String> = emptyList()
|
override val stateKeys: List<String> = emptyList()
|
||||||
|
|
||||||
@ -39,18 +39,12 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
|
|
||||||
demo("dynamic", "Dynamic properties") {
|
demo("dynamic", "Dynamic properties") {
|
||||||
val group = group {
|
val group = group {
|
||||||
box {
|
box(100, 100, 100) {
|
||||||
z = 110.0
|
z = 110.0
|
||||||
xSize = 100.0
|
|
||||||
ySize = 100.0
|
|
||||||
zSize = 100.0
|
|
||||||
}
|
}
|
||||||
box {
|
box(100, 100, 100) {
|
||||||
visible = false
|
visible = false
|
||||||
x = 110.0
|
x = 110.0
|
||||||
xSize = 100.0
|
|
||||||
ySize = 100.0
|
|
||||||
zSize = 100.0
|
|
||||||
//override color for this cube
|
//override color for this cube
|
||||||
color(1530)
|
color(1530)
|
||||||
|
|
||||||
@ -63,7 +57,7 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var material by group.properties.number(1530).int
|
var material by group.config.number(1530).int
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
val random = Random(111)
|
val random = Random(111)
|
||||||
@ -100,34 +94,28 @@ class ThreeDemoApp : ApplicationBase() {
|
|||||||
demo("CSG", "CSG operations") {
|
demo("CSG", "CSG operations") {
|
||||||
composite(CompositeType.UNION) {
|
composite(CompositeType.UNION) {
|
||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 100
|
z = 50
|
||||||
rotationX = PI / 4
|
|
||||||
rotationY = PI / 4
|
|
||||||
}
|
}
|
||||||
box(100, 100, 100)
|
sphere(50)
|
||||||
color {
|
color {
|
||||||
"color" to Colors.lightgreen
|
"color" to Colors.lightgreen
|
||||||
"opacity" to 0.3
|
"opacity" to 0.3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
composite(CompositeType.INTERSECT) {
|
composite(CompositeType.INTERSECT) {
|
||||||
box(100, 100, 100) {
|
|
||||||
z = 100
|
|
||||||
rotationX = PI / 4
|
|
||||||
rotationY = PI / 4
|
|
||||||
}
|
|
||||||
box(100, 100, 100)
|
|
||||||
y = 300
|
y = 300
|
||||||
|
box(100, 100, 100) {
|
||||||
|
z = 50
|
||||||
|
}
|
||||||
|
sphere(50)
|
||||||
color(Colors.red)
|
color(Colors.red)
|
||||||
}
|
}
|
||||||
composite(CompositeType.SUBTRACT) {
|
composite(CompositeType.SUBTRACT) {
|
||||||
box(100, 100, 100) {
|
|
||||||
z = 100
|
|
||||||
rotationX = PI / 4
|
|
||||||
rotationY = PI / 4
|
|
||||||
}
|
|
||||||
box(100, 100, 100)
|
|
||||||
y = -300
|
y = -300
|
||||||
|
box(100, 100, 100) {
|
||||||
|
z = 50
|
||||||
|
}
|
||||||
|
sphere(50)
|
||||||
color(Colors.blue)
|
color(Colors.blue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,9 +11,9 @@ object ThreeCylinderFactory : MeshThreeFactory<Cylinder>(Cylinder::class) {
|
|||||||
return obj.detail?.let {
|
return obj.detail?.let {
|
||||||
val segments = it.toDouble().pow(0.5).toInt()
|
val segments = it.toDouble().pow(0.5).toInt()
|
||||||
CylinderBufferGeometry(
|
CylinderBufferGeometry(
|
||||||
radiusTop = obj.upperRadius!!,
|
radiusTop = obj.upperRadius,
|
||||||
radiusBottom = obj.radius!!,
|
radiusBottom = obj.radius,
|
||||||
height = obj.height!!,
|
height = obj.height,
|
||||||
radialSegments = segments,
|
radialSegments = segments,
|
||||||
heightSegments = segments,
|
heightSegments = segments,
|
||||||
openEnded = false,
|
openEnded = false,
|
||||||
@ -21,9 +21,9 @@ object ThreeCylinderFactory : MeshThreeFactory<Cylinder>(Cylinder::class) {
|
|||||||
thetaLength = obj.angle
|
thetaLength = obj.angle
|
||||||
)
|
)
|
||||||
} ?: CylinderBufferGeometry(
|
} ?: CylinderBufferGeometry(
|
||||||
radiusTop = obj.upperRadius!!,
|
radiusTop = obj.upperRadius,
|
||||||
radiusBottom = obj.radius!!,
|
radiusBottom = obj.radius,
|
||||||
height = obj.height!!,
|
height = obj.height,
|
||||||
openEnded = false,
|
openEnded = false,
|
||||||
thetaStart = obj.startAngle,
|
thetaStart = obj.startAngle,
|
||||||
thetaLength = obj.angle
|
thetaLength = obj.angle
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package hep.dataforge.vis.spatial.three
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
import hep.dataforge.meta.boolean
|
import hep.dataforge.meta.boolean
|
||||||
|
import hep.dataforge.meta.get
|
||||||
import hep.dataforge.names.startsWith
|
import hep.dataforge.names.startsWith
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import hep.dataforge.provider.Type
|
import hep.dataforge.provider.Type
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.getProperty
|
|
||||||
import hep.dataforge.vis.common.onChange
|
import hep.dataforge.vis.common.onChange
|
||||||
import hep.dataforge.vis.spatial.*
|
import hep.dataforge.vis.spatial.*
|
||||||
import hep.dataforge.vis.spatial.three.ThreeFactory.Companion.TYPE
|
import hep.dataforge.vis.spatial.three.ThreeFactory.Companion.TYPE
|
||||||
@ -19,7 +18,7 @@ import info.laht.threekt.objects.LineSegments
|
|||||||
import info.laht.threekt.objects.Mesh
|
import info.laht.threekt.objects.Mesh
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
internal val VisualObject.material get() = getProperty("material").material()
|
internal val VisualObject.material get() = properties["material"].material()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder and updater for three.js object
|
* Builder and updater for three.js object
|
||||||
@ -43,14 +42,14 @@ interface ThreeFactory<T : VisualObject> {
|
|||||||
val mesh = Mesh(geometry, obj.material)
|
val mesh = Mesh(geometry, obj.material)
|
||||||
|
|
||||||
//inherited edges definition, enabled by default
|
//inherited edges definition, enabled by default
|
||||||
if (obj.getProperty("edges.enabled").boolean != false) {
|
if (obj.properties["edges.enabled"].boolean != false) {
|
||||||
val material = obj.getProperty("edges.material")?.material() ?: Materials.DEFAULT
|
val material = obj.properties["edges.material"]?.material() ?: Materials.DEFAULT
|
||||||
mesh.add(LineSegments(EdgesGeometry(mesh.geometry as BufferGeometry), material))
|
mesh.add(LineSegments(EdgesGeometry(mesh.geometry as BufferGeometry), material))
|
||||||
}
|
}
|
||||||
|
|
||||||
//inherited wireframe definition, disabled by default
|
//inherited wireframe definition, disabled by default
|
||||||
if (obj.getProperty("wireframe.enabled").boolean == true) {
|
if (obj.properties["wireframe.enabled"].boolean == true) {
|
||||||
val material = obj.getProperty("edges.material")?.material() ?: Materials.DEFAULT
|
val material = obj.properties["edges.material"]?.material() ?: Materials.DEFAULT
|
||||||
mesh.add(LineSegments(WireframeGeometry(mesh.geometry as BufferGeometry), material))
|
mesh.add(LineSegments(WireframeGeometry(mesh.geometry as BufferGeometry), material))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,9 +62,9 @@ interface ThreeFactory<T : VisualObject> {
|
|||||||
//updated material
|
//updated material
|
||||||
mesh.material = obj.material
|
mesh.material = obj.material
|
||||||
} else if (
|
} else if (
|
||||||
name.startsWith("pos".toName()) ||
|
name.startsWith(PropertyNames3D.position) ||
|
||||||
name.startsWith("scale".toName()) ||
|
name.startsWith(PropertyNames3D.rotation) ||
|
||||||
name.startsWith("rotation".toName()) ||
|
name.startsWith(PropertyNames3D.scale) ||
|
||||||
name.toString() == "visible"
|
name.toString() == "visible"
|
||||||
) {
|
) {
|
||||||
//update position of mesh using this object
|
//update position of mesh using this object
|
||||||
|
@ -38,7 +38,14 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
|
|
||||||
fun buildObject3D(obj: VisualObject): Object3D {
|
fun buildObject3D(obj: VisualObject): Object3D {
|
||||||
return when (obj) {
|
return when (obj) {
|
||||||
is VisualGroup -> Group(obj.map { buildObject3D(it) }).apply {
|
is VisualGroup -> Group(obj.mapNotNull {
|
||||||
|
try {
|
||||||
|
buildObject3D(it)
|
||||||
|
} catch (ex: Throwable){
|
||||||
|
logger.error(ex){"Failed to render $it"}
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}).apply {
|
||||||
updatePosition(obj)
|
updatePosition(obj)
|
||||||
}
|
}
|
||||||
is Composite -> compositeFactory(obj)
|
is Composite -> compositeFactory(obj)
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.EmptyMeta
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
import hep.dataforge.vis.common.DisplayLeaf
|
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.double
|
|
||||||
|
|
||||||
class Box(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape {
|
class Box(parent: VisualObject?, val xSize: Number, val ySize: Number, val zSize: Number, meta: Array<out Meta>) :
|
||||||
var xSize by double(100.0)
|
VisualObject3D(parent, meta), Shape {
|
||||||
var ySize by double(100.0)
|
|
||||||
var zSize by double(100.0)
|
|
||||||
|
|
||||||
//TODO add helper for color configuration
|
//TODO add helper for color configuration
|
||||||
|
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
val dx = xSize / 2
|
val dx = xSize.toDouble() / 2
|
||||||
val dy = ySize / 2
|
val dy = ySize.toDouble() / 2
|
||||||
val dz = zSize / 2
|
val dz = zSize.toDouble() / 2
|
||||||
val node1 = Point3D(-dx, -dy, -dz)
|
val node1 = Point3D(-dx, -dy, -dz)
|
||||||
val node2 = Point3D(dx, -dy, -dz)
|
val node2 = Point3D(dx, -dy, -dz)
|
||||||
val node3 = Point3D(dx, dy, -dz)
|
val node3 = Point3D(dx, dy, -dz)
|
||||||
@ -40,12 +35,15 @@ class Box(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.box(meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
|
//fun VisualGroup.box(meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
|
||||||
Box(this, meta).apply(action).also { add(it) }
|
// Box(this, meta).apply(action).also { add(it) }
|
||||||
|
|
||||||
fun VisualGroup.box(xSize: Number, ySize: Number, zSize: Number, meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
|
fun VisualGroup.box(
|
||||||
Box(this, meta).apply(action).apply{
|
xSize: Number,
|
||||||
this.xSize = xSize.toDouble()
|
ySize: Number,
|
||||||
this.ySize = ySize.toDouble()
|
zSize: Number,
|
||||||
this.zSize = zSize.toDouble()
|
name: String? = null,
|
||||||
}.also { add(it) }
|
vararg meta: Meta,
|
||||||
|
action: Box.() -> Unit = {}
|
||||||
|
) =
|
||||||
|
Box(this, xSize, ySize, zSize, meta).apply(action).also { set(name, it) }
|
@ -1,9 +1,8 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.EmptyMeta
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.seal
|
import hep.dataforge.meta.seal
|
||||||
import hep.dataforge.vis.common.DisplayLeaf
|
import hep.dataforge.meta.update
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
|
||||||
@ -13,28 +12,35 @@ enum class CompositeType {
|
|||||||
SUBTRACT
|
SUBTRACT
|
||||||
}
|
}
|
||||||
|
|
||||||
class Composite(
|
open class Composite(
|
||||||
parent: VisualObject?,
|
parent: VisualObject?,
|
||||||
val first: VisualObject,
|
val first: VisualObject,
|
||||||
val second: VisualObject,
|
val second: VisualObject,
|
||||||
val type: CompositeType = CompositeType.UNION,
|
val type: CompositeType = CompositeType.UNION,
|
||||||
meta: Meta = EmptyMeta
|
meta: Array<out Meta>
|
||||||
) : DisplayLeaf(parent, meta)
|
) : VisualObject3D(parent, meta)
|
||||||
|
|
||||||
fun VisualGroup.composite(type: CompositeType, builder: VisualGroup.() -> Unit): Composite {
|
fun VisualGroup.composite(
|
||||||
|
type: CompositeType,
|
||||||
|
name: String? = null,
|
||||||
|
vararg meta: Meta,
|
||||||
|
builder: VisualGroup.() -> Unit
|
||||||
|
): Composite {
|
||||||
val group = VisualGroup().apply(builder)
|
val group = VisualGroup().apply(builder)
|
||||||
val children = group.toList()
|
val children = group.toList()
|
||||||
if (children.size != 2) error("Composite requires exactly two children")
|
if (children.size != 2) error("Composite requires exactly two children")
|
||||||
return Composite(this, children[0], children[1], type, group.properties.seal()).also {
|
val groupMeta = group.properties.seal()
|
||||||
this.add(it)
|
return Composite(this, children[0], children[1], type, meta).also {
|
||||||
|
it.config.update(groupMeta)
|
||||||
|
set(name, it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.union(builder: VisualGroup.() -> Unit) =
|
fun VisualGroup.union(name: String? = null, vararg meta: Meta, builder: VisualGroup.() -> Unit) =
|
||||||
composite(CompositeType.UNION,builder)
|
composite(CompositeType.UNION, name, *meta, builder = builder)
|
||||||
|
|
||||||
fun VisualGroup.subtract(builder: VisualGroup.() -> Unit) =
|
fun VisualGroup.subtract(name: String? = null, vararg meta: Meta, builder: VisualGroup.() -> Unit) =
|
||||||
composite(CompositeType.SUBTRACT,builder)
|
composite(CompositeType.SUBTRACT, name, *meta, builder = builder)
|
||||||
|
|
||||||
fun VisualGroup.intersect(builder: VisualGroup.() -> Unit) =
|
fun VisualGroup.intersect(name: String? = null, vararg meta: Meta, builder: VisualGroup.() -> Unit) =
|
||||||
composite(CompositeType.INTERSECT,builder)
|
composite(CompositeType.INTERSECT, name, *meta, builder = builder)
|
@ -1,26 +1,19 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
import hep.dataforge.vis.common.DisplayLeaf
|
import hep.dataforge.vis.common.VisualLeaf
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
|
||||||
class Convex(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
|
class Convex(parent: VisualObject?, val points: List<Point3D>, meta: Array<out Meta>) : VisualLeaf(parent, meta) {
|
||||||
|
|
||||||
val points = points(properties["points"] ?: error("Vertices not defined"))
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE = "geometry.3d.convex"
|
const val TYPE = "geometry.3d.convex"
|
||||||
|
|
||||||
fun points(item: MetaItem<*>): List<Point3D> {
|
|
||||||
return item.node?.getAll("point")?.map { (_, value) ->
|
|
||||||
Point3D.from(value.node?: error("Point definition is not a node"))
|
|
||||||
} ?: emptyList()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.convex(meta: Meta = EmptyMeta, action: ConvexBuilder.() -> Unit = {}) =
|
fun VisualGroup.convex(vararg meta: Meta, action: ConvexBuilder.() -> Unit = {}) =
|
||||||
ConvexBuilder().apply(action).build(this, meta).also { add(it) }
|
ConvexBuilder().apply(action).build(this, meta).also { add(it) }
|
||||||
|
|
||||||
class ConvexBuilder {
|
class ConvexBuilder {
|
||||||
@ -30,13 +23,7 @@ class ConvexBuilder {
|
|||||||
points.add(Point3D(x, y, z))
|
points.add(Point3D(x, y, z))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(parent: VisualObject?, meta: Meta): Convex {
|
fun build(parent: VisualObject?, meta: Array<out Meta>): Convex {
|
||||||
val points = buildMeta {
|
return Convex(parent, points, meta)
|
||||||
points.forEachIndexed { index, value ->
|
|
||||||
"points.point[$index]" to value.toMeta()
|
|
||||||
}
|
|
||||||
}.seal()
|
|
||||||
|
|
||||||
return Convex(parent, points)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,9 +1,8 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.EmptyMeta
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.vis.common.DisplayLeaf
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
|
import hep.dataforge.vis.common.VisualLeaf
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.number
|
import hep.dataforge.vis.common.number
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
@ -11,18 +10,23 @@ import kotlin.math.PI
|
|||||||
/**
|
/**
|
||||||
* A cylinder or cut cone segment
|
* A cylinder or cut cone segment
|
||||||
*/
|
*/
|
||||||
class Cylinder(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
|
class Cylinder(parent: VisualObject?, radius: Number, height: Number, meta: Array<out Meta>) :
|
||||||
var radius by number()
|
VisualLeaf(parent, meta) {
|
||||||
var upperRadius by number(default = radius)
|
var radius by number(radius)
|
||||||
var height by number()
|
var upperRadius by number(radius)
|
||||||
|
var height by number(height)
|
||||||
var startAngle by number(0.0)
|
var startAngle by number(0.0)
|
||||||
var angle by number(2 * PI)
|
var angle by number(2 * PI)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.cylinder(r: Number, height: Number, meta: Meta = EmptyMeta, block: Cylinder.() -> Unit = {}): Cylinder {
|
fun VisualGroup.cylinder(
|
||||||
val cylinder = Cylinder(this, meta)
|
r: Number,
|
||||||
cylinder.radius = r
|
height: Number,
|
||||||
cylinder.height = height
|
name: String? = null,
|
||||||
|
vararg meta: Meta,
|
||||||
|
block: Cylinder.() -> Unit = {}
|
||||||
|
): Cylinder {
|
||||||
|
val cylinder = Cylinder(this, r, height, meta)
|
||||||
cylinder.apply(block)
|
cylinder.apply(block)
|
||||||
return cylinder.also { add(it) }
|
return cylinder.also { set(name, it) }
|
||||||
}
|
}
|
@ -1,8 +1,8 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.vis.common.DisplayLeaf
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
|
import hep.dataforge.vis.common.VisualLeaf
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
@ -18,7 +18,7 @@ class Shape2DBuilder {
|
|||||||
list.add(Point2D(x, y))
|
list.add(Point2D(x, y))
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Number.to(y:Number) = point(this, y)
|
infix fun Number.to(y: Number) = point(this, y)
|
||||||
|
|
||||||
fun build(): Shape2D = list
|
fun build(): Shape2D = list
|
||||||
}
|
}
|
||||||
@ -31,45 +31,22 @@ fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Layer(override val config: Config) : Specific {
|
data class Layer(var x: Number, var y: Number, var z: Number, var scale: Number)
|
||||||
var z by number(0.0)
|
|
||||||
var x by number(0.0)
|
|
||||||
var y by number(0.0)
|
|
||||||
var scale by number(1.0)
|
|
||||||
|
|
||||||
companion object : Specification<Layer> {
|
class Extruded(parent: VisualObject?, meta: Array<out Meta>) : VisualLeaf(parent, meta), Shape {
|
||||||
override fun wrap(config: Config): Layer = Layer(config)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//class Layer(val z: Number, val x: Number = 0.0, val y: Number = 0.0, val scale: Number = 1.0)
|
var shape: List<Point2D> = ArrayList()
|
||||||
|
|
||||||
class Extruded(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta), Shape {
|
|
||||||
|
|
||||||
val shape
|
|
||||||
get() = properties.getAll("shape.point").map { (_, value) ->
|
|
||||||
Point2D.from(value.node ?: error("Point definition is not a node"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun shape(block: Shape2DBuilder.() -> Unit) {
|
fun shape(block: Shape2DBuilder.() -> Unit) {
|
||||||
val points = Shape2DBuilder().apply(block).build().map { it.toMeta() }
|
this.shape = Shape2DBuilder().apply(block).build()
|
||||||
properties["shape.point"] = points
|
//TODO send invalidation signal
|
||||||
}
|
}
|
||||||
|
|
||||||
val layers
|
val layers: MutableList<Layer> = ArrayList()
|
||||||
get() = properties.getAll("layer").values.map {
|
|
||||||
Layer.wrap(it.node ?: error("layer item is not a node"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0): Layer {
|
fun layer(z: Number, x: Number = 0.0, y: Number = 0.0, scale: Number = 1.0) {
|
||||||
val layer = Layer.build {
|
layers.add(Layer(x,y,z,scale))
|
||||||
this.x = x
|
//TODO send invalidation signal
|
||||||
this.y = y
|
|
||||||
this.z = z
|
|
||||||
this.scale = scale
|
|
||||||
}
|
|
||||||
properties.append("layer", layer)
|
|
||||||
return layer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||||
@ -121,5 +98,5 @@ class Extruded(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta), S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.extrude(meta: Meta = EmptyMeta, action: Extruded.() -> Unit = {}) =
|
fun VisualGroup.extrude(name: String? = null, vararg meta: Meta, action: Extruded.() -> Unit = {}) =
|
||||||
Extruded(this, meta).apply(action).also { add(it) }
|
Extruded(this, meta).apply(action).also { set(name, it) }
|
@ -1,14 +1,13 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.EmptyMeta
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
import hep.dataforge.vis.common.DisplayLeaf
|
import hep.dataforge.vis.common.VisualLeaf
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import hep.dataforge.vis.common.double
|
import hep.dataforge.vis.common.double
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
class Sphere(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
|
class Sphere(parent: VisualObject?, meta: Array<out Meta>) : VisualLeaf(parent, meta) {
|
||||||
var radius by double(50.0)
|
var radius by double(50.0)
|
||||||
var phiStart by double(0.0)
|
var phiStart by double(0.0)
|
||||||
var phi by double(2 * PI)
|
var phi by double(2 * PI)
|
||||||
@ -16,17 +15,15 @@ class Sphere(parent: VisualObject?, meta: Meta) : DisplayLeaf(parent, meta) {
|
|||||||
var theta by double(PI)
|
var theta by double(PI)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.sphere(meta: Meta = EmptyMeta, action: Sphere.() -> Unit = {}) =
|
|
||||||
Sphere(this, meta).apply(action).also { add(it) }
|
|
||||||
|
|
||||||
fun VisualGroup.sphere(
|
fun VisualGroup.sphere(
|
||||||
radius: Number,
|
radius: Number,
|
||||||
phi: Number = 2 * PI,
|
phi: Number = 2 * PI,
|
||||||
theta: Number = PI,
|
theta: Number = PI,
|
||||||
meta: Meta = EmptyMeta,
|
name: String? = null,
|
||||||
|
vararg meta: Meta,
|
||||||
action: Sphere.() -> Unit = {}
|
action: Sphere.() -> Unit = {}
|
||||||
) = Sphere(this, meta).apply(action).apply {
|
) = Sphere(this, meta).apply(action).apply {
|
||||||
this.radius = radius.toDouble()
|
this.radius = radius.toDouble()
|
||||||
this.phi = phi.toDouble()
|
this.phi = phi.toDouble()
|
||||||
this.theta = theta.toDouble()
|
this.theta = theta.toDouble()
|
||||||
}.also { add(it) }
|
}.also { set(name, it) }
|
@ -0,0 +1,196 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
import hep.dataforge.names.plus
|
||||||
|
import hep.dataforge.output.Output
|
||||||
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
|
import hep.dataforge.vis.common.VisualLeaf
|
||||||
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
import hep.dataforge.vis.common.asName
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performance optimized version of visual object
|
||||||
|
*/
|
||||||
|
open class VisualObject3D(parent: VisualObject?, tagRefs: Array<out Meta>) : VisualLeaf(parent, tagRefs) {
|
||||||
|
var x: Number? = null; get() = field ?: (this as VisualLeaf).x
|
||||||
|
var y: Number? = null; get() = field ?: (this as VisualLeaf).y
|
||||||
|
var z: Number? = null; get() = field ?: (this as VisualLeaf).z
|
||||||
|
|
||||||
|
var rotationX: Number? = null; get() = field ?: (this as VisualLeaf).rotationX
|
||||||
|
var rotationY: Number? = null; get() = field ?: (this as VisualLeaf).rotationY
|
||||||
|
var rotationZ: Number? = null; get() = field ?: (this as VisualLeaf).rotationZ
|
||||||
|
}
|
||||||
|
|
||||||
|
fun VisualGroup.group(key: String? = null, vararg meta: Meta, action: VisualGroup.() -> Unit = {}): VisualGroup =
|
||||||
|
VisualGroup(this, meta).apply(action).also { set(key, it) }
|
||||||
|
|
||||||
|
|
||||||
|
fun Output<VisualObject>.render(meta: Meta = EmptyMeta, action: VisualGroup.() -> Unit) =
|
||||||
|
render(VisualGroup().apply(action), meta)
|
||||||
|
|
||||||
|
//TODO replace properties by containers?
|
||||||
|
|
||||||
|
object PropertyNames3D {
|
||||||
|
val x = "x".asName()
|
||||||
|
val y = "y".asName()
|
||||||
|
val z = "z".asName()
|
||||||
|
|
||||||
|
val position = "pos".asName()
|
||||||
|
|
||||||
|
val xPos = position + x
|
||||||
|
val yPos = position + y
|
||||||
|
val zPos = position + z
|
||||||
|
|
||||||
|
val rotation = "rotation".asName()
|
||||||
|
|
||||||
|
val xRotation = rotation + x
|
||||||
|
val yRotation = rotation + y
|
||||||
|
val zRotation = rotation + z
|
||||||
|
|
||||||
|
val rotationOrder = rotation + "order"
|
||||||
|
|
||||||
|
val scale = "scale".asName()
|
||||||
|
|
||||||
|
val xScale = scale + x
|
||||||
|
val yScale = scale + y
|
||||||
|
val zScale = scale + z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common properties
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Visibility property. Inherited from parent
|
||||||
|
*/
|
||||||
|
var VisualObject.visible
|
||||||
|
get() = properties["visible"].boolean ?: true
|
||||||
|
set(value) {
|
||||||
|
config["visible"] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3D Object position
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x position property relative to parent. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.x
|
||||||
|
get() = config[PropertyNames3D.xPos].number ?: 0.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.xPos] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* y position property. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.y
|
||||||
|
get() = config[PropertyNames3D.yPos].number ?: 0.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.yPos] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* z position property. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.z
|
||||||
|
get() = config[PropertyNames3D.zPos].number ?: 0.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.zPos] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3D Object rotation
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* x rotation relative to parent. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.rotationX
|
||||||
|
get() = config[PropertyNames3D.xRotation].number ?: 0.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.xRotation] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* y rotation relative to parent. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.rotationY
|
||||||
|
get() = config[PropertyNames3D.yRotation].number ?: 0.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.yRotation] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* z rotation relative to parent. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.rotationZ
|
||||||
|
get() = config[PropertyNames3D.zRotation].number ?: 0.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.zRotation] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class RotationOrder {
|
||||||
|
XYZ,
|
||||||
|
YZX,
|
||||||
|
ZXY,
|
||||||
|
XZY,
|
||||||
|
YXZ,
|
||||||
|
ZYX
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotation order. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.rotationOrder: RotationOrder
|
||||||
|
get() = config[PropertyNames3D.rotationOrder].enum<RotationOrder>() ?: RotationOrder.XYZ
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.rotationOrder] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3D object scale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* X scale. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.scaleX
|
||||||
|
get() = config[PropertyNames3D.xScale].number ?: 1.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.xScale] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Y scale. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.scaleY
|
||||||
|
get() = config[PropertyNames3D.yScale].number ?: 1.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.yScale] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Z scale. Not inherited
|
||||||
|
*/
|
||||||
|
var VisualObject.scaleZ
|
||||||
|
get() = config[PropertyNames3D.zScale].number ?: 1.0
|
||||||
|
set(value) {
|
||||||
|
config[PropertyNames3D.zScale] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO add inherited scale
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default
|
||||||
|
*/
|
||||||
|
var VisualObject.detail: Int?
|
||||||
|
get() = properties["detail"]?.int
|
||||||
|
set(value) {
|
||||||
|
config["detail"] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
object World {
|
||||||
|
const val CAMERA_INITIAL_DISTANCE = -500.0
|
||||||
|
const val CAMERA_INITIAL_X_ANGLE = -50.0
|
||||||
|
const val CAMERA_INITIAL_Y_ANGLE = 0.0
|
||||||
|
const val CAMERA_INITIAL_Z_ANGLE = -210.0
|
||||||
|
const val CAMERA_NEAR_CLIP = 0.1
|
||||||
|
const val CAMERA_FAR_CLIP = 10000.0
|
||||||
|
}
|
@ -1,164 +0,0 @@
|
|||||||
package hep.dataforge.vis.spatial
|
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import hep.dataforge.output.Output
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
import hep.dataforge.vis.common.VisualObject
|
|
||||||
import hep.dataforge.vis.common.getProperty
|
|
||||||
|
|
||||||
fun VisualGroup.group(meta: Meta = EmptyMeta, action: VisualGroup.() -> Unit = {}): VisualGroup =
|
|
||||||
VisualGroup(this, meta).apply(action).also { add(it) }
|
|
||||||
|
|
||||||
|
|
||||||
fun Output<VisualObject>.render(meta: Meta = EmptyMeta, action: VisualGroup.() -> Unit) =
|
|
||||||
render(VisualGroup(null, EmptyMeta).apply(action), meta)
|
|
||||||
|
|
||||||
//TODO replace properties by containers?
|
|
||||||
|
|
||||||
// Common properties
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Visibility property. Inherited from parent
|
|
||||||
*/
|
|
||||||
var VisualObject.visible
|
|
||||||
get() = getProperty("visible").boolean ?: true
|
|
||||||
set(value) {
|
|
||||||
properties["visible"] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D Object position
|
|
||||||
|
|
||||||
private val xPos = "pos.x".toName()
|
|
||||||
/**
|
|
||||||
* x position property relative to parent. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.x
|
|
||||||
get() = properties[xPos].number ?: 0.0
|
|
||||||
set(value) {
|
|
||||||
properties[xPos] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
private val yPos = "pos.y".toName()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* y position property. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.y
|
|
||||||
get() = properties[yPos].number ?: 0.0
|
|
||||||
set(value) {
|
|
||||||
properties[yPos] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
private val zPos = "pos.z".toName()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* z position property. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.z
|
|
||||||
get() = properties[zPos].number ?: 0.0
|
|
||||||
set(value) {
|
|
||||||
properties[zPos] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D Object rotation
|
|
||||||
|
|
||||||
private val xRotation = "rotation.x".toName()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* x rotation relative to parent. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.rotationX
|
|
||||||
get() = properties[xRotation].number ?: 0.0
|
|
||||||
set(value) {
|
|
||||||
properties[xRotation] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
private val yRotation = "rotation.y".toName()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* y rotation relative to parent. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.rotationY
|
|
||||||
get() = properties[yRotation].number ?: 0.0
|
|
||||||
set(value) {
|
|
||||||
properties[yRotation] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
private val zRotation = "rotation.z".toName()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* z rotation relative to parent. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.rotationZ
|
|
||||||
get() = properties[zRotation].number ?: 0.0
|
|
||||||
set(value) {
|
|
||||||
properties[zRotation] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class RotationOrder {
|
|
||||||
XYZ,
|
|
||||||
YZX,
|
|
||||||
ZXY,
|
|
||||||
XZY,
|
|
||||||
YXZ,
|
|
||||||
ZYX
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rotation order. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.rotationOrder: RotationOrder
|
|
||||||
get() = getProperty("rotation.order").enum<RotationOrder>() ?: RotationOrder.XYZ
|
|
||||||
set(value) {
|
|
||||||
properties["rotation.order"] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3D object scale
|
|
||||||
|
|
||||||
/**
|
|
||||||
* X scale. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.scaleX
|
|
||||||
get() = properties["scale.x"].number ?: 1.0
|
|
||||||
set(value) {
|
|
||||||
properties["scale.x"] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Y scale. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.scaleY
|
|
||||||
get() = properties["scale.y"].number ?: 1.0
|
|
||||||
set(value) {
|
|
||||||
properties["scale.y"] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Z scale. Not inherited
|
|
||||||
*/
|
|
||||||
var VisualObject.scaleZ
|
|
||||||
get() = properties["scale.z"].number ?: 1.0
|
|
||||||
set(value) {
|
|
||||||
properties["scale.z"] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO add inherited scale
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default
|
|
||||||
*/
|
|
||||||
var VisualObject.detail: Int?
|
|
||||||
get() = properties["detail"]?.int
|
|
||||||
set(value) {
|
|
||||||
properties["detail"] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
object World {
|
|
||||||
const val CAMERA_INITIAL_DISTANCE = -500.0
|
|
||||||
const val CAMERA_INITIAL_X_ANGLE = -50.0
|
|
||||||
const val CAMERA_INITIAL_Y_ANGLE = 0.0
|
|
||||||
const val CAMERA_INITIAL_Z_ANGLE = -210.0
|
|
||||||
const val CAMERA_NEAR_CLIP = 0.1
|
|
||||||
const val CAMERA_FAR_CLIP = 10000.0
|
|
||||||
}
|
|
@ -26,7 +26,7 @@ class ConvexTest {
|
|||||||
|
|
||||||
val convex = group.first() as Convex
|
val convex = group.first() as Convex
|
||||||
|
|
||||||
val pointsNode = convex.properties["points"].node
|
val pointsNode = convex.config["points"].node
|
||||||
|
|
||||||
assertEquals(8, pointsNode?.items?.count())
|
assertEquals(8, pointsNode?.items?.count())
|
||||||
val points = pointsNode?.getAll("point".toName())
|
val points = pointsNode?.getAll("point".toName())
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
import hep.dataforge.vis.common.Colors
|
||||||
|
import hep.dataforge.vis.common.VisualGroup
|
||||||
|
import hep.dataforge.vis.common.color
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class GroupTest {
|
||||||
|
@Test
|
||||||
|
fun testGroupWithComposite(){
|
||||||
|
val group = VisualGroup().apply{
|
||||||
|
union {
|
||||||
|
box(100, 100, 100) {
|
||||||
|
z = 100
|
||||||
|
rotationX = PI / 4
|
||||||
|
rotationY = PI / 4
|
||||||
|
}
|
||||||
|
box(100, 100, 100)
|
||||||
|
color {
|
||||||
|
"color" to Colors.lightgreen
|
||||||
|
"opacity" to 0.3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intersect{
|
||||||
|
box(100, 100, 100) {
|
||||||
|
z = 100
|
||||||
|
rotationX = PI / 4
|
||||||
|
rotationY = PI / 4
|
||||||
|
}
|
||||||
|
box(100, 100, 100)
|
||||||
|
y = 300
|
||||||
|
color(Colors.red)
|
||||||
|
}
|
||||||
|
subtract{
|
||||||
|
box(100, 100, 100) {
|
||||||
|
z = 100
|
||||||
|
rotationX = PI / 4
|
||||||
|
rotationY = PI / 4
|
||||||
|
}
|
||||||
|
box(100, 100, 100)
|
||||||
|
y = -300
|
||||||
|
color(Colors.blue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(3, group.count())
|
||||||
|
assertEquals(300.0,group.toList()[1].y.toDouble())
|
||||||
|
assertEquals(-300.0,group.toList()[2].y.toDouble())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user