forked from kscience/visionforge
Added caching for geometries
This commit is contained in:
parent
997a5a8e60
commit
cf5a4fd7f6
@ -1,4 +1,4 @@
|
|||||||
val dataforgeVersion by extra("0.1.3-dev-9")
|
val dataforgeVersion by extra("0.1.3-dev-10")
|
||||||
|
|
||||||
plugins{
|
plugins{
|
||||||
val kotlinVersion = "1.3.50-eap-5"
|
val kotlinVersion = "1.3.50-eap-5"
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
package hep.dataforge.vis.common
|
|
||||||
|
|
||||||
import hep.dataforge.meta.Config
|
|
||||||
import hep.dataforge.meta.Laminate
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.names.Name
|
|
||||||
import hep.dataforge.provider.Provider
|
|
||||||
import kotlin.collections.set
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A display group which allows both named and unnamed children
|
|
||||||
*/
|
|
||||||
open class VisualGroup(
|
|
||||||
override val parent: VisualObject? = null, tagRefs: Array<out Meta> = emptyArray()
|
|
||||||
) : VisualObject, Iterable<VisualObject>, Provider {
|
|
||||||
|
|
||||||
private val namedChildren = HashMap<Name, VisualObject>()
|
|
||||||
private val unnamedChildren = ArrayList<VisualObject>()
|
|
||||||
|
|
||||||
override val defaultTarget: String get() = VisualObject.TYPE
|
|
||||||
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 provideTop(target: String): Map<Name, Any> {
|
|
||||||
return when (target) {
|
|
||||||
VisualObject.TYPE -> namedChildren
|
|
||||||
else -> emptyMap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private data class Listener(val owner: Any?, val callback: (Name?, VisualObject?) -> Unit)
|
|
||||||
|
|
||||||
private val listeners = HashSet<Listener>()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add listener for children change
|
|
||||||
*/
|
|
||||||
fun onChildrenChange(owner: Any?, action: (Name?, VisualObject?) -> 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: VisualObject?) {
|
|
||||||
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: VisualObject?) = set(key?.asName(), child)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append unnamed child
|
|
||||||
*/
|
|
||||||
fun add(child: VisualObject) {
|
|
||||||
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) }
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,29 @@
|
|||||||
|
package hep.dataforge.vis.common
|
||||||
|
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basic [VisualObject] leaf element
|
||||||
|
*/
|
||||||
|
open class VisualLeaf(
|
||||||
|
parent: VisualObject? = null,
|
||||||
|
meta: Meta = EmptyMeta
|
||||||
|
) : AbstractVisualObject(parent), Configurable {
|
||||||
|
|
||||||
|
val properties = Styled(meta)
|
||||||
|
|
||||||
|
override val config: Config = properties.style
|
||||||
|
|
||||||
|
override fun setProperty(name: Name, value: Any?) {
|
||||||
|
config[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||||
|
return if (inherit) {
|
||||||
|
properties[name] ?: parent?.getProperty(name, inherit)
|
||||||
|
} else {
|
||||||
|
properties[name]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,11 @@ 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.get
|
||||||
|
import hep.dataforge.provider.Provider
|
||||||
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.TAGS_KEY
|
|
||||||
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
|
import hep.dataforge.vis.common.VisualObject.Companion.TYPE
|
||||||
|
import kotlin.collections.set
|
||||||
|
|
||||||
private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
private fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
||||||
private fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
private fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
||||||
@ -16,88 +17,190 @@ private fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
|||||||
@Type(TYPE)
|
@Type(TYPE)
|
||||||
interface VisualObject : MetaRepr, Configurable {
|
interface VisualObject : MetaRepr, Configurable {
|
||||||
|
|
||||||
|
val type: String get() = this::class.simpleName ?: TYPE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Individual properties configurator
|
* Set property for this object
|
||||||
*/
|
*/
|
||||||
override val config: Config
|
fun setProperty(name: Name, value: Any?)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All properties including inherited ones
|
* Get property including or excluding parent properties
|
||||||
*/
|
*/
|
||||||
val properties: Laminate
|
fun getProperty(name: Name, inherit: Boolean = true): MetaItem<*>?
|
||||||
|
|
||||||
override fun toMeta(): Meta = buildMeta {
|
/**
|
||||||
"type" to this::class
|
* Manually trigger property changed event. If [name] is empty, notify that the whole object is changed
|
||||||
"properties" to properties
|
*/
|
||||||
}
|
fun propertyChanged(name: Name, before: MetaItem<*>? = null, after: MetaItem<*>? = null): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add listener triggering on property change
|
||||||
|
*/
|
||||||
|
fun onPropertyChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit): Unit
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove change listeners with given owner.
|
||||||
|
*/
|
||||||
|
fun removeChangeListener(owner: Any?)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE = "visual"
|
const val TYPE = "visual"
|
||||||
|
|
||||||
const val DEFAULT_TYPE = ""
|
//const val META_KEY = "@meta"
|
||||||
//const val TYPE_KEY = "@type"
|
//const val TAGS_KEY = "@tags"
|
||||||
//const val CHILDREN_KEY = "@children"
|
|
||||||
const val META_KEY = "@meta"
|
|
||||||
const val TAGS_KEY = "@tags"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
internal data class MetaListener(
|
||||||
* A change listener for [VisualObject] configuration.
|
val owner: Any? = null,
|
||||||
*/
|
val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
|
||||||
fun VisualObject.onChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit) {
|
)
|
||||||
config.onChange(owner, action)
|
|
||||||
parent?.onChange(owner, action)
|
|
||||||
|
abstract class AbstractVisualObject(override val parent: VisualObject?) : VisualObject {
|
||||||
|
private val listeners = HashSet<MetaListener>()
|
||||||
|
|
||||||
|
override fun propertyChanged(name: Name, before: MetaItem<*>?, after: MetaItem<*>?) {
|
||||||
|
for (l in listeners) {
|
||||||
|
l.action(name, before, after)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onPropertyChange(owner: Any?, action: (Name, before: MetaItem<*>?, after: MetaItem<*>?) -> Unit) {
|
||||||
|
listeners.add(MetaListener(owner, action))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun removeChangeListener(owner: Any?) {
|
||||||
|
listeners.removeAll { it.owner == owner }
|
||||||
|
}
|
||||||
|
|
||||||
|
private var _config: Config? = null
|
||||||
|
override val config: Config get() = _config ?: Config().also { _config = it }
|
||||||
|
|
||||||
|
override fun setProperty(name: Name, value: Any?) {
|
||||||
|
config[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||||
|
return if (inherit) {
|
||||||
|
_config?.get(name) ?: parent?.getProperty(name, inherit)
|
||||||
|
} else {
|
||||||
|
_config?.get(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun MetaBuilder.updateMeta() {}
|
||||||
|
|
||||||
|
override fun toMeta(): Meta = buildMeta {
|
||||||
|
"type" to type
|
||||||
|
"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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class Listener<T : VisualObject>(val owner: Any?, val callback: (Name?, T?) -> Unit)
|
||||||
|
|
||||||
|
private val listeners = HashSet<Listener<T>>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all meta listeners with matching owners
|
* Add listener for children change
|
||||||
*/
|
*/
|
||||||
fun VisualObject.removeChangeListener(owner: Any?) {
|
fun onChildrenChange(owner: Any?, action: (Name?, T?) -> Unit) {
|
||||||
config.removeListener(owner)
|
listeners.add(Listener(owner, action))
|
||||||
parent?.removeChangeListener(owner)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Additional meta not relevant to display
|
* Remove children change listener
|
||||||
*/
|
*/
|
||||||
val VisualObject.meta: Meta get() = config[META_KEY]?.node ?: EmptyMeta
|
fun removeChildrenChangeListener(owner: Any?) {
|
||||||
|
listeners.removeAll { it.owner === owner }
|
||||||
val VisualObject.tags: List<String> get() = config[TAGS_KEY].stringList
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic [VisualObject] leaf element
|
* 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.
|
||||||
*/
|
*/
|
||||||
open class VisualLeaf(
|
operator fun set(name: Name?, child: T?) {
|
||||||
final override val parent: VisualObject?,
|
when {
|
||||||
tagRefs: Array<out Meta>
|
name != null -> {
|
||||||
) : VisualObject {
|
if (child == null) {
|
||||||
override val config = Config()
|
namedChildren.remove(name)
|
||||||
|
} else {
|
||||||
override val properties: Laminate by lazy {
|
namedChildren[name] = child
|
||||||
combineProperties(parent, config, tagRefs)
|
}
|
||||||
|
listeners.forEach { it.callback(name, child) }
|
||||||
|
}
|
||||||
|
child != null -> unnamedChildren.add(child)
|
||||||
|
else -> error("Both key and child element are empty")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun combineProperties(parent: VisualObject?, config: Config, tagRefs: Array<out Meta>): Laminate {
|
operator fun set(key: String?, child: T?) = set(key?.asName(), child)
|
||||||
val list = ArrayList<Meta>(tagRefs.size + 2)
|
|
||||||
list += config
|
/**
|
||||||
list.addAll(tagRefs)
|
* Get named child by name
|
||||||
parent?.properties?.let { list.add(it) }
|
*/
|
||||||
return Laminate(list)
|
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) }
|
||||||
}
|
}
|
||||||
|
|
||||||
///**
|
/**
|
||||||
// * A group that could contain both named and unnamed children. Unnamed children could be accessed only via
|
* remove unnamed child
|
||||||
// */
|
*/
|
||||||
//interface VisualGroup : DisplayObject, Iterable<DisplayObject>, Provider {
|
fun remove(child: VisualObject) {
|
||||||
// override val defaultTarget: String get() = DisplayObject.TARGET
|
unnamedChildren.remove(child)
|
||||||
//
|
listeners.forEach { it.callback(null, null) }
|
||||||
// val children
|
}
|
||||||
//}
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ class DisplayObjectDelegate(
|
|||||||
override fun getValue(thisRef: VisualObject, property: KProperty<*>): MetaItem<*>? {
|
override fun getValue(thisRef: VisualObject, property: KProperty<*>): MetaItem<*>? {
|
||||||
val name = key ?: property.name.asName()
|
val name = key ?: property.name.asName()
|
||||||
return if (inherited) {
|
return if (inherited) {
|
||||||
thisRef.properties[name]
|
thisRef.getProperty(name)
|
||||||
} else {
|
} else {
|
||||||
thisRef.config[name]
|
thisRef.config[name]
|
||||||
} ?: default
|
} ?: default
|
||||||
@ -48,7 +48,7 @@ class DisplayObjectDelegateWrapper<T>(
|
|||||||
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
override fun getValue(thisRef: VisualObject, property: KProperty<*>): T {
|
||||||
val name = key ?: property.name.asName()
|
val name = key ?: property.name.asName()
|
||||||
return if (inherited) {
|
return if (inherited) {
|
||||||
read(thisRef.properties[name])
|
read(thisRef.getProperty(name))
|
||||||
} else {
|
} else {
|
||||||
read(thisRef.config[name])
|
read(thisRef.config[name])
|
||||||
} ?: default
|
} ?: default
|
||||||
|
@ -3,7 +3,7 @@ package hep.dataforge.vis.spatial
|
|||||||
import hep.dataforge.context.Context
|
import hep.dataforge.context.Context
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.output.Output
|
import hep.dataforge.output.Output
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
import hep.dataforge.vis.common.VisualNode
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
import javafx.scene.Group
|
import javafx.scene.Group
|
||||||
import javafx.scene.Node
|
import javafx.scene.Node
|
||||||
@ -27,7 +27,7 @@ class FX3DOutput(override val context: Context) : Output<VisualObject> {
|
|||||||
org.fxyz3d.geometry.Point3D(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f)
|
org.fxyz3d.geometry.Point3D(x.value ?: 0f, y.value ?: 0f, z.value ?: 0f)
|
||||||
}
|
}
|
||||||
return when (obj) {
|
return when (obj) {
|
||||||
is VisualGroup -> Group(obj.map { buildNode(it) }).apply {
|
is VisualNode -> Group(obj.map { buildNode(it) }).apply {
|
||||||
this.translateXProperty().bind(x)
|
this.translateXProperty().bind(x)
|
||||||
this.translateYProperty().bind(y)
|
this.translateYProperty().bind(y)
|
||||||
this.translateZProperty().bind(z)
|
this.translateZProperty().bind(z)
|
||||||
|
@ -2,7 +2,6 @@ package hep.dataforge.vis.spatial
|
|||||||
|
|
||||||
import hep.dataforge.context.Global
|
import hep.dataforge.context.Global
|
||||||
import hep.dataforge.meta.number
|
import hep.dataforge.meta.number
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
import javafx.scene.Parent
|
import javafx.scene.Parent
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -21,7 +20,7 @@ class RendererDemoView : View() {
|
|||||||
center = renderer.canvas.root
|
center = renderer.canvas.root
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var group: VisualGroup
|
lateinit var group: VisualGroup3D
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.buildMeta
|
||||||
|
import hep.dataforge.meta.builder
|
||||||
|
import hep.dataforge.vis.spatial.VisualGroup3D
|
||||||
|
import scientifik.gdml.GDML
|
||||||
|
import scientifik.gdml.GDMLGroup
|
||||||
|
import scientifik.gdml.GDMLMaterial
|
||||||
|
import scientifik.gdml.GDMLSolid
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
class GDMLTransformer(val root: GDML) {
|
||||||
|
private val materialCache = HashMap<GDMLMaterial, Meta>()
|
||||||
|
private val random = Random(111)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A special group for local templates
|
||||||
|
*/
|
||||||
|
val templates by lazy { VisualGroup3D() }
|
||||||
|
|
||||||
|
var lUnit: LUnit = LUnit.MM
|
||||||
|
var resolveColor: ColorResolver = { material, _ ->
|
||||||
|
val materialColor = materialCache.getOrPut(material) {
|
||||||
|
buildMeta {
|
||||||
|
"color" to random.nextInt(0, Int.MAX_VALUE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this?.physVolumes?.isEmpty() != false) {
|
||||||
|
materialColor
|
||||||
|
} else {
|
||||||
|
materialColor.builder().apply { "opacity" to 0.5 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var acceptSolid: (GDMLSolid) -> Boolean = { true }
|
||||||
|
var acceptGroup: (GDMLGroup) -> Boolean = { true }
|
||||||
|
|
||||||
|
fun printStatistics() {
|
||||||
|
println("Solids:")
|
||||||
|
solidCounter.entries.sortedByDescending { it.value }.forEach {
|
||||||
|
println("\t$it")
|
||||||
|
}
|
||||||
|
println(println("Solids total: ${solidCounter.values.sum()}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
private val solidCounter = HashMap<String, Int>()
|
||||||
|
|
||||||
|
internal fun solidAdded(solid: GDMLSolid) {
|
||||||
|
solidCounter[solid.name] = (solidCounter[solid.name] ?: 0) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
var onFinish: GDMLTransformer.() -> Unit = {}
|
||||||
|
|
||||||
|
internal fun finished() {
|
||||||
|
onFinish(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,58 +1,10 @@
|
|||||||
package hep.dataforge.vis.spatial.gdml
|
package hep.dataforge.vis.spatial.gdml
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.buildMeta
|
|
||||||
import hep.dataforge.meta.builder
|
|
||||||
import hep.dataforge.vis.spatial.*
|
import hep.dataforge.vis.spatial.*
|
||||||
import scientifik.gdml.*
|
import scientifik.gdml.*
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
|
|
||||||
class GDMLTransformer(val root: GDML) {
|
|
||||||
private val cache = HashMap<GDMLMaterial, Meta>()
|
|
||||||
private val random = Random(111)
|
|
||||||
|
|
||||||
var lUnit: LUnit = LUnit.MM
|
|
||||||
var resolveColor: ColorResolver = { material, _ ->
|
|
||||||
val materialColor = cache.getOrPut(material) {
|
|
||||||
buildMeta {
|
|
||||||
"color" to random.nextInt(0, Int.MAX_VALUE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this?.physVolumes?.isEmpty() != false) {
|
|
||||||
materialColor
|
|
||||||
} else {
|
|
||||||
materialColor.builder().apply { "opacity" to 0.5 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var acceptSolid: (GDMLSolid) -> Boolean = { true }
|
|
||||||
var acceptGroup: (GDMLGroup) -> Boolean = { true }
|
|
||||||
|
|
||||||
fun printStatistics() {
|
|
||||||
println("Solids:")
|
|
||||||
solidCounter.entries.sortedByDescending { it.value }.forEach {
|
|
||||||
println("\t$it")
|
|
||||||
}
|
|
||||||
println(println("Solids total: ${solidCounter.values.sum()}"))
|
|
||||||
}
|
|
||||||
|
|
||||||
private val solidCounter = HashMap<String, Int>()
|
|
||||||
|
|
||||||
internal fun solidAdded(solid: GDMLSolid) {
|
|
||||||
solidCounter[solid.name] = (solidCounter[solid.name] ?: 0) + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
var onFinish: GDMLTransformer.() -> Unit = {}
|
|
||||||
|
|
||||||
internal fun finished(){
|
|
||||||
onFinish(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun VisualObject3D.withPosition(
|
private fun VisualObject3D.withPosition(
|
||||||
@ -82,7 +34,6 @@ private fun VisualObject3D.withPosition(
|
|||||||
private inline operator fun Number.times(d: Double) = toDouble() * d
|
private inline operator fun Number.times(d: Double) = toDouble() * d
|
||||||
private inline operator fun Number.times(f: Float) = toFloat() * f
|
private inline operator fun Number.times(f: Float) = toFloat() * f
|
||||||
|
|
||||||
|
|
||||||
private fun VisualGroup3D.addSolid(
|
private fun VisualGroup3D.addSolid(
|
||||||
context: GDMLTransformer,
|
context: GDMLTransformer,
|
||||||
solid: GDMLSolid,
|
solid: GDMLSolid,
|
||||||
@ -238,9 +189,12 @@ private fun volume(
|
|||||||
val material = group.materialref.resolve(context.root) ?: GDMLElement(group.materialref.ref)
|
val material = group.materialref.resolve(context.root) ?: GDMLElement(group.materialref.ref)
|
||||||
|
|
||||||
if (context.acceptSolid(solid)) {
|
if (context.acceptSolid(solid)) {
|
||||||
addSolid(context, solid, solid.name) {
|
val cachedSolid = context.templates[solid.name]
|
||||||
|
?: context.templates.addSolid(context, solid, solid.name) {
|
||||||
this.material = context.resolveColor(group, material, solid)
|
this.material = context.resolveColor(group, material, solid)
|
||||||
}
|
}
|
||||||
|
val wrapper = Proxy3D(this,cachedSolid)
|
||||||
|
add(wrapper)
|
||||||
}
|
}
|
||||||
|
|
||||||
when (val vol = group.placement) {
|
when (val vol = group.placement) {
|
||||||
|
@ -90,11 +90,11 @@ private class GDMLDemoApp : ApplicationBase() {
|
|||||||
launch { message("Converting GDML into DF-VIS format") }
|
launch { message("Converting GDML into DF-VIS format") }
|
||||||
val visual = gdml.toVisual {
|
val visual = gdml.toVisual {
|
||||||
lUnit = LUnit.CM
|
lUnit = LUnit.CM
|
||||||
acceptSolid = { solid ->
|
// acceptSolid = { solid ->
|
||||||
!solid.name.startsWith("ecal")
|
// !solid.name.startsWith("ecal")
|
||||||
&& !solid.name.startsWith("V")
|
// && !solid.name.startsWith("V")
|
||||||
&& !solid.name.startsWith("U")
|
// && !solid.name.startsWith("U")
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
launch { message("Rendering") }
|
launch { message("Rendering") }
|
||||||
val output = three.output(canvas)
|
val output = three.output(canvas)
|
||||||
|
@ -18,7 +18,7 @@ fun main() {
|
|||||||
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||||
xml.toVisual {
|
xml.toVisual {
|
||||||
lUnit = LUnit.CM
|
lUnit = LUnit.CM
|
||||||
acceptSolid = { solid -> !solid.name.startsWith("ecal") && !solid.name.startsWith("V") }
|
//acceptSolid = { solid -> !solid.name.startsWith("ecal") && !solid.name.startsWith("V") }
|
||||||
onFinish = { printStatistics() }
|
onFinish = { printStatistics() }
|
||||||
}
|
}
|
||||||
readLine()
|
readLine()
|
||||||
|
@ -40,6 +40,8 @@ fun MetaItem<*>.color(): Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val materialCache = HashMap<Meta, Material>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Infer Three material based on meta item
|
* Infer Three material based on meta item
|
||||||
*/
|
*/
|
||||||
@ -47,7 +49,8 @@ fun Meta?.jsMaterial(): Material {
|
|||||||
return if (this == null) {
|
return if (this == null) {
|
||||||
Materials.DEFAULT
|
Materials.DEFAULT
|
||||||
} else
|
} else
|
||||||
//TODO add more oprions for material
|
//TODO add more options for material
|
||||||
|
return materialCache.getOrPut(this) {
|
||||||
MeshBasicMaterial().apply {
|
MeshBasicMaterial().apply {
|
||||||
color = get("color")?.color() ?: Materials.DEFAULT_COLOR
|
color = get("color")?.color() ?: Materials.DEFAULT_COLOR
|
||||||
opacity = get("opacity")?.double ?: 1.0
|
opacity = get("opacity")?.double ?: 1.0
|
||||||
@ -55,6 +58,6 @@ fun Meta?.jsMaterial(): Material {
|
|||||||
//node["specularColor"]?.let { specular = it.color() }
|
//node["specularColor"]?.let { specular = it.color() }
|
||||||
side = 2
|
side = 2
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ class ThreeCompositeFactory(val three: ThreePlugin) : MeshThreeFactory<Composite
|
|||||||
second.updateMatrix()
|
second.updateMatrix()
|
||||||
val firstCSG = CSG.fromMesh(first)
|
val firstCSG = CSG.fromMesh(first)
|
||||||
val secondCSG = CSG.fromMesh(second)
|
val secondCSG = CSG.fromMesh(second)
|
||||||
val resultCSG = when (obj.type) {
|
val resultCSG = when (obj.compositeType) {
|
||||||
CompositeType.UNION -> firstCSG.union(secondCSG)
|
CompositeType.UNION -> firstCSG.union(secondCSG)
|
||||||
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
|
CompositeType.INTERSECT -> firstCSG.intersect(secondCSG)
|
||||||
CompositeType.SUBTRACT -> firstCSG.subtract(secondCSG)
|
CompositeType.SUBTRACT -> firstCSG.subtract(secondCSG)
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
|
import hep.dataforge.vis.spatial.Convex
|
||||||
|
import info.laht.threekt.external.geometries.ConvexBufferGeometry
|
||||||
|
|
||||||
|
object ThreeConvexFactory : MeshThreeFactory<Convex>(Convex::class) {
|
||||||
|
override fun buildGeometry(obj: Convex): ConvexBufferGeometry {
|
||||||
|
val vectors = obj.points.map { it.asVector() }.toTypedArray()
|
||||||
|
return ConvexBufferGeometry(vectors)
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,16 @@
|
|||||||
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.meta.int
|
import hep.dataforge.meta.int
|
||||||
import hep.dataforge.meta.node
|
import hep.dataforge.meta.node
|
||||||
|
import hep.dataforge.names.plus
|
||||||
import hep.dataforge.names.startsWith
|
import hep.dataforge.names.startsWith
|
||||||
import hep.dataforge.provider.Type
|
import hep.dataforge.provider.Type
|
||||||
import hep.dataforge.vis.common.onChange
|
import hep.dataforge.vis.common.asName
|
||||||
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
|
||||||
import hep.dataforge.vis.spatial.three.ThreeFactory.Companion.buildMesh
|
|
||||||
import info.laht.threekt.core.BufferGeometry
|
import info.laht.threekt.core.BufferGeometry
|
||||||
import info.laht.threekt.core.Object3D
|
import info.laht.threekt.core.Object3D
|
||||||
import info.laht.threekt.external.geometries.ConvexBufferGeometry
|
|
||||||
import info.laht.threekt.geometries.EdgesGeometry
|
import info.laht.threekt.geometries.EdgesGeometry
|
||||||
import info.laht.threekt.geometries.WireframeGeometry
|
import info.laht.threekt.geometries.WireframeGeometry
|
||||||
import info.laht.threekt.objects.LineSegments
|
import info.laht.threekt.objects.LineSegments
|
||||||
@ -31,55 +29,6 @@ interface ThreeFactory<T : VisualObject3D> {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE = "threeFactory"
|
const val TYPE = "threeFactory"
|
||||||
|
|
||||||
fun <T : VisualObject3D> buildMesh(obj: T, geometryBuilder: (T) -> BufferGeometry): Mesh {
|
|
||||||
val geometry = geometryBuilder(obj)
|
|
||||||
|
|
||||||
//JS sometimes tries to pass Geometry as BufferGeometry
|
|
||||||
@Suppress("USELESS_IS_CHECK") if (geometry !is BufferGeometry) error("BufferGeometry expected")
|
|
||||||
|
|
||||||
val mesh = Mesh(geometry, obj.material.jsMaterial())
|
|
||||||
|
|
||||||
//inherited edges definition, enabled by default
|
|
||||||
if (obj.properties["edges.enabled"].boolean != false) {
|
|
||||||
val material = obj.properties["edges.material"].node?.jsMaterial() ?: Materials.DEFAULT
|
|
||||||
mesh.add(LineSegments(EdgesGeometry(mesh.geometry as BufferGeometry), material))
|
|
||||||
}
|
|
||||||
|
|
||||||
//inherited wireframe definition, disabled by default
|
|
||||||
if (obj.properties["wireframe.enabled"].boolean == true) {
|
|
||||||
val material = obj.properties["wireframe.material"].node?.jsMaterial() ?: Materials.DEFAULT
|
|
||||||
mesh.add(LineSegments(WireframeGeometry(mesh.geometry as BufferGeometry), material))
|
|
||||||
}
|
|
||||||
|
|
||||||
//set position for mesh
|
|
||||||
mesh.updatePosition(obj)
|
|
||||||
|
|
||||||
obj.config["layer"].int?.let {
|
|
||||||
mesh.layers.set(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
//add listener to object properties
|
|
||||||
obj.onChange(this) { name, _, _ ->
|
|
||||||
if (name.startsWith(VisualObject3D.materialKey)) {
|
|
||||||
//updated material
|
|
||||||
mesh.material = obj.material.jsMaterial()
|
|
||||||
} else if (
|
|
||||||
name.startsWith(VisualObject3D.position) ||
|
|
||||||
name.startsWith(VisualObject3D.rotation) ||
|
|
||||||
name.startsWith(VisualObject3D.scale) ||
|
|
||||||
name == VisualObject3D.visibleKey
|
|
||||||
) {
|
|
||||||
//update position of mesh using this object
|
|
||||||
mesh.updatePosition(obj)
|
|
||||||
} else {
|
|
||||||
//full update
|
|
||||||
mesh.geometry = geometryBuilder(obj)
|
|
||||||
mesh.material = obj.material.jsMaterial()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mesh
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +39,30 @@ internal fun Object3D.updatePosition(obj: VisualObject3D) {
|
|||||||
position.set(obj.x, obj.y, obj.z)
|
position.set(obj.x, obj.y, obj.z)
|
||||||
setRotationFromEuler(obj.euler)
|
setRotationFromEuler(obj.euler)
|
||||||
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
scale.set(obj.scaleX, obj.scaleY, obj.scaleZ)
|
||||||
visible = obj.visible ?: true
|
updateMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <T : VisualObject3D> Mesh.updateFrom(obj: T) {
|
||||||
|
matrixAutoUpdate = false
|
||||||
|
|
||||||
|
//inherited edges definition, enabled by default
|
||||||
|
if (obj.getProperty(MeshThreeFactory.EDGES_ENABLED_KEY).boolean != false) {
|
||||||
|
val material = obj.getProperty(MeshThreeFactory.EDGES_MATERIAL_KEY).node?.jsMaterial() ?: Materials.DEFAULT
|
||||||
|
add(LineSegments(EdgesGeometry(geometry as BufferGeometry), material))
|
||||||
|
}
|
||||||
|
|
||||||
|
//inherited wireframe definition, disabled by default
|
||||||
|
if (obj.getProperty(MeshThreeFactory.WIREFRAME_ENABLED_KEY).boolean == true) {
|
||||||
|
val material = obj.getProperty(MeshThreeFactory.WIREFRAME_MATERIAL_KEY).node?.jsMaterial() ?: Materials.DEFAULT
|
||||||
|
add(LineSegments(WireframeGeometry(geometry as BufferGeometry), material))
|
||||||
|
}
|
||||||
|
|
||||||
|
//set position for mesh
|
||||||
|
updatePosition(obj)
|
||||||
|
|
||||||
|
obj.getProperty(MeshThreeFactory.LAYER_KEY).int?.let {
|
||||||
|
layers.set(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,6 +90,51 @@ abstract class MeshThreeFactory<T : VisualObject3D>(override val type: KClass<ou
|
|||||||
//create mesh from geometry
|
//create mesh from geometry
|
||||||
return buildMesh<T>(obj) { buildGeometry(it) }
|
return buildMesh<T>(obj) { buildGeometry(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val EDGES_KEY = "edges".asName()
|
||||||
|
val WIREFRAME_KEY = "wireframe".asName()
|
||||||
|
val ENABLED_KEY = "enabled".asName()
|
||||||
|
val EDGES_ENABLED_KEY = EDGES_KEY + ENABLED_KEY
|
||||||
|
val EDGES_MATERIAL_KEY = EDGES_KEY + VisualObject3D.MATERIAL_KEY
|
||||||
|
val WIREFRAME_ENABLED_KEY = WIREFRAME_KEY + ENABLED_KEY
|
||||||
|
val WIREFRAME_MATERIAL_KEY = WIREFRAME_KEY + VisualObject3D.MATERIAL_KEY
|
||||||
|
val LAYER_KEY = "layer".asName()
|
||||||
|
|
||||||
|
fun <T : VisualObject3D> buildMesh(obj: T, geometryBuilder: (T) -> BufferGeometry): Mesh {
|
||||||
|
//TODO add caching for geometries using templates
|
||||||
|
val geometry = geometryBuilder(obj)
|
||||||
|
|
||||||
|
//JS sometimes tries to pass Geometry as BufferGeometry
|
||||||
|
@Suppress("USELESS_IS_CHECK") if (geometry !is BufferGeometry) error("BufferGeometry expected")
|
||||||
|
|
||||||
|
val mesh = Mesh(geometry, obj.material.jsMaterial())
|
||||||
|
|
||||||
|
mesh.updateFrom(obj)
|
||||||
|
|
||||||
|
//add listener to object properties
|
||||||
|
obj.onPropertyChange(this) { name, _, _ ->
|
||||||
|
if (name.startsWith(VisualObject3D.MATERIAL_KEY)) {
|
||||||
|
//updated material
|
||||||
|
mesh.material = obj.material.jsMaterial()
|
||||||
|
} else if (
|
||||||
|
name.startsWith(VisualObject3D.position) ||
|
||||||
|
name.startsWith(VisualObject3D.rotation) ||
|
||||||
|
name.startsWith(VisualObject3D.scale)
|
||||||
|
) {
|
||||||
|
//update position of mesh using this object
|
||||||
|
mesh.updatePosition(obj)
|
||||||
|
} else if (name == VisualObject3D.VISIBLE_KEY) {
|
||||||
|
obj.visible = obj.visible ?: true
|
||||||
|
} else {
|
||||||
|
//full update
|
||||||
|
mesh.geometry = geometryBuilder(obj)
|
||||||
|
mesh.material = obj.material.jsMaterial()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mesh
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,11 +147,3 @@ object ThreeShapeFactory : MeshThreeFactory<Shape>(Shape::class) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME not functional yet
|
|
||||||
object ThreeConvexFactory : MeshThreeFactory<Convex>(Convex::class) {
|
|
||||||
override fun buildGeometry(obj: Convex): ConvexBufferGeometry {
|
|
||||||
val vectors = obj.points.map { it.asVector() }.toTypedArray()
|
|
||||||
return ConvexBufferGeometry(vectors)
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
|
|
||||||
private val objectFactories = HashMap<KClass<out VisualObject3D>, ThreeFactory<*>>()
|
private val objectFactories = HashMap<KClass<out VisualObject3D>, ThreeFactory<*>>()
|
||||||
private val compositeFactory = ThreeCompositeFactory(this)
|
private val compositeFactory = ThreeCompositeFactory(this)
|
||||||
|
private val proxyFactory = ThreeProxyFactory(this)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
//Add specialized factories here
|
//Add specialized factories here
|
||||||
@ -38,7 +39,6 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
return when (obj) {
|
return when (obj) {
|
||||||
is VisualGroup3D -> Group(obj.mapNotNull {
|
is VisualGroup3D -> Group(obj.mapNotNull {
|
||||||
try {
|
try {
|
||||||
it as VisualObject3D
|
|
||||||
buildObject3D(it)
|
buildObject3D(it)
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
console.error(ex)
|
console.error(ex)
|
||||||
@ -49,6 +49,7 @@ class ThreePlugin : AbstractPlugin() {
|
|||||||
updatePosition(obj)
|
updatePosition(obj)
|
||||||
}
|
}
|
||||||
is Composite -> compositeFactory(obj)
|
is Composite -> compositeFactory(obj)
|
||||||
|
is Proxy3D -> proxyFactory(obj)
|
||||||
else -> {
|
else -> {
|
||||||
//find specialized factory for this type if it is present
|
//find specialized factory for this type if it is present
|
||||||
val factory = findObjectFactory(obj::class)
|
val factory = findObjectFactory(obj::class)
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package hep.dataforge.vis.spatial.three
|
||||||
|
|
||||||
|
import hep.dataforge.vis.spatial.Proxy3D
|
||||||
|
import hep.dataforge.vis.spatial.VisualObject3D
|
||||||
|
import info.laht.threekt.core.BufferGeometry
|
||||||
|
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>()
|
||||||
|
|
||||||
|
override val type = Proxy3D::class
|
||||||
|
|
||||||
|
override fun invoke(obj: Proxy3D): Object3D {
|
||||||
|
val templateMesh = cache.getOrPut(obj.template) {
|
||||||
|
three.buildObject3D(obj.template) as Mesh
|
||||||
|
}
|
||||||
|
|
||||||
|
val mesh = Mesh(templateMesh.geometry as BufferGeometry, templateMesh.material)
|
||||||
|
//val mesh = templateMesh.clone()
|
||||||
|
|
||||||
|
mesh.updatePosition(obj)
|
||||||
|
return mesh
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,9 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
|
||||||
class Box(parent: VisualObject?, val xSize: Number, val ySize: Number, val zSize: Number, meta: Array<out Meta>) :
|
class Box(parent: VisualObject?, val xSize: Number, val ySize: Number, val zSize: Number) :
|
||||||
VisualLeaf3D(parent, meta), Shape {
|
VisualLeaf3D(parent), Shape {
|
||||||
|
|
||||||
//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>) {
|
||||||
@ -34,14 +32,10 @@ class Box(parent: VisualObject?, val xSize: Number, val ySize: Number, val zSize
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//fun VisualGroup.box(meta: Meta = EmptyMeta, action: Box.() -> Unit = {}) =
|
inline fun VisualGroup3D.box(
|
||||||
// Box(this, meta).apply(action).also { add(it) }
|
|
||||||
|
|
||||||
inline fun VisualGroup.box(
|
|
||||||
xSize: Number,
|
xSize: Number,
|
||||||
ySize: Number,
|
ySize: Number,
|
||||||
zSize: Number,
|
zSize: Number,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
vararg meta: Meta,
|
|
||||||
action: Box.() -> Unit = {}
|
action: Box.() -> Unit = {}
|
||||||
) = Box(this, xSize, ySize, zSize, meta).apply(action).also { set(name, it) }
|
) = Box(this, xSize, ySize, zSize).apply(action).also { set(name, it) }
|
@ -1,9 +1,7 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.meta.isEmpty
|
import hep.dataforge.meta.isEmpty
|
||||||
import hep.dataforge.meta.update
|
import hep.dataforge.meta.update
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
|
||||||
enum class CompositeType {
|
enum class CompositeType {
|
||||||
@ -16,20 +14,18 @@ open class Composite(
|
|||||||
parent: VisualObject?,
|
parent: VisualObject?,
|
||||||
val first: VisualObject3D,
|
val first: VisualObject3D,
|
||||||
val second: VisualObject3D,
|
val second: VisualObject3D,
|
||||||
val type: CompositeType = CompositeType.UNION,
|
val compositeType: CompositeType = CompositeType.UNION
|
||||||
meta: Array<out Meta>
|
) : VisualLeaf3D(parent)
|
||||||
) : VisualLeaf3D(parent, meta)
|
|
||||||
|
|
||||||
fun VisualGroup.composite(
|
fun VisualGroup3D.composite(
|
||||||
type: CompositeType,
|
type: CompositeType,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
vararg meta: Meta,
|
|
||||||
builder: VisualGroup3D.() -> Unit
|
builder: VisualGroup3D.() -> Unit
|
||||||
): Composite {
|
): Composite {
|
||||||
val group = VisualGroup3D().apply(builder)
|
val group = VisualGroup3D().apply(builder)
|
||||||
val children = group.filterIsInstance<VisualObject3D>()
|
val children = group.filterIsInstance<VisualObject3D>()
|
||||||
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, meta).also {
|
return Composite(this, children[0], children[1], type).also {
|
||||||
if (!group.config.isEmpty()) {
|
if (!group.config.isEmpty()) {
|
||||||
it.config.update(group.config)
|
it.config.update(group.config)
|
||||||
}
|
}
|
||||||
@ -41,11 +37,11 @@ fun VisualGroup.composite(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup3D.union(name: String? = null, vararg meta: Meta, builder: VisualGroup3D.() -> Unit) =
|
fun VisualGroup3D.union(name: String? = null, builder: VisualGroup3D.() -> Unit) =
|
||||||
composite(CompositeType.UNION, name, *meta, builder = builder)
|
composite(CompositeType.UNION, name, builder = builder)
|
||||||
|
|
||||||
fun VisualGroup3D.subtract(name: String? = null, vararg meta: Meta, builder: VisualGroup3D.() -> Unit) =
|
fun VisualGroup3D.subtract(name: String? = null, builder: VisualGroup3D.() -> Unit) =
|
||||||
composite(CompositeType.SUBTRACT, name, *meta, builder = builder)
|
composite(CompositeType.SUBTRACT, name, builder = builder)
|
||||||
|
|
||||||
fun VisualGroup3D.intersect(name: String? = null, vararg meta: Meta, builder: VisualGroup3D.() -> Unit) =
|
fun VisualGroup3D.intersect(name: String? = null, builder: VisualGroup3D.() -> Unit) =
|
||||||
composite(CompositeType.INTERSECT, name, *meta, builder = builder)
|
composite(CompositeType.INTERSECT, name, builder = builder)
|
@ -1,10 +1,8 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
import hep.dataforge.vis.common.VisualObject
|
import hep.dataforge.vis.common.VisualObject
|
||||||
|
|
||||||
class Convex(parent: VisualObject?, val points: List<Point3D>, meta: Array<out Meta>) : VisualLeaf3D(parent, meta) {
|
class Convex(parent: VisualObject?, val points: List<Point3D>) : VisualLeaf3D(parent) {
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -12,8 +10,8 @@ class Convex(parent: VisualObject?, val points: List<Point3D>, meta: Array<out M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.convex(vararg meta: Meta, action: ConvexBuilder.() -> Unit = {}) =
|
fun VisualGroup3D.convex(action: ConvexBuilder.() -> Unit = {}) =
|
||||||
ConvexBuilder().apply(action).build(this, meta).also { add(it) }
|
ConvexBuilder().apply(action).build(this).also { add(it) }
|
||||||
|
|
||||||
class ConvexBuilder {
|
class ConvexBuilder {
|
||||||
private val points = ArrayList<Point3D>()
|
private val points = ArrayList<Point3D>()
|
||||||
@ -22,7 +20,7 @@ class ConvexBuilder {
|
|||||||
points.add(Point3D(x, y, z))
|
points.add(Point3D(x, y, z))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun build(parent: VisualObject?, meta: Array<out Meta>): Convex {
|
fun build(parent: VisualObject?): Convex {
|
||||||
return Convex(parent, points, meta)
|
return Convex(parent, points)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
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
|
||||||
@ -9,21 +7,19 @@ import kotlin.math.PI
|
|||||||
/**
|
/**
|
||||||
* A cylinder or cut cone segment
|
* A cylinder or cut cone segment
|
||||||
*/
|
*/
|
||||||
class Cylinder(parent: VisualObject?, var radius: Number, var height: Number, meta: Array<out Meta>) :
|
class Cylinder(parent: VisualObject?, var radius: Number, var height: Number) : VisualLeaf3D(parent) {
|
||||||
VisualLeaf3D(parent, meta) {
|
|
||||||
var upperRadius by number(radius)
|
var upperRadius by number(radius)
|
||||||
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(
|
fun VisualGroup3D.cylinder(
|
||||||
r: Number,
|
r: Number,
|
||||||
height: Number,
|
height: Number,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
vararg meta: Meta,
|
|
||||||
block: Cylinder.() -> Unit = {}
|
block: Cylinder.() -> Unit = {}
|
||||||
): Cylinder {
|
): Cylinder {
|
||||||
val cylinder = Cylinder(this, r, height, meta)
|
val cylinder = Cylinder(this, r, height)
|
||||||
cylinder.apply(block)
|
cylinder.apply(block)
|
||||||
return cylinder.also { set(name, it) }
|
return cylinder.also { set(name, it) }
|
||||||
}
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
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
|
||||||
@ -32,7 +30,7 @@ fun Shape2DBuilder.polygon(vertices: Int, radius: Number) {
|
|||||||
|
|
||||||
data class Layer(var x: Number, var y: Number, var z: Number, var scale: Number)
|
data class Layer(var x: Number, var y: Number, var z: Number, var scale: Number)
|
||||||
|
|
||||||
class Extruded(parent: VisualObject?, meta: Array<out Meta>) : VisualLeaf3D(parent, meta), Shape {
|
class Extruded(parent: VisualObject?) : VisualLeaf3D(parent), Shape {
|
||||||
|
|
||||||
var shape: List<Point2D> = ArrayList()
|
var shape: List<Point2D> = ArrayList()
|
||||||
|
|
||||||
@ -112,5 +110,5 @@ class Extruded(parent: VisualObject?, meta: Array<out Meta>) : VisualLeaf3D(pare
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.extrude(name: String? = null, vararg meta: Meta, action: Extruded.() -> Unit = {}) =
|
fun VisualGroup3D.extrude(name: String? = null, action: Extruded.() -> Unit = {}) =
|
||||||
Extruded(this, meta).apply(action).also { set(name, it) }
|
Extruded(this).apply(action).also { set(name, it) }
|
@ -0,0 +1,34 @@
|
|||||||
|
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,26 +1,23 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
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
|
||||||
|
|
||||||
class Sphere(parent: VisualObject?, var radius: Number, meta: Array<out Meta>) : VisualLeaf3D(parent, meta) {
|
class Sphere(parent: VisualObject?, var radius: Number) : VisualLeaf3D(parent) {
|
||||||
var phiStart by number(0.0)
|
var phiStart by number(0.0)
|
||||||
var phi by number(2 * PI)
|
var phi by number(2 * PI)
|
||||||
var thetaStart by number(0.0)
|
var thetaStart by number(0.0)
|
||||||
var theta by number(PI)
|
var theta by number(PI)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun VisualGroup.sphere(
|
fun VisualGroup3D.sphere(
|
||||||
radius: Number,
|
radius: Number,
|
||||||
phi: Number = 2 * PI,
|
phi: Number = 2 * PI,
|
||||||
theta: Number = PI,
|
theta: Number = PI,
|
||||||
name: String? = null,
|
name: String? = null,
|
||||||
vararg meta: Meta,
|
|
||||||
action: Sphere.() -> Unit = {}
|
action: Sphere.() -> Unit = {}
|
||||||
) = Sphere(this, radius, meta).apply(action).apply {
|
) = Sphere(this, radius).apply(action).apply {
|
||||||
this.phi = phi.toDouble()
|
this.phi = phi.toDouble()
|
||||||
this.theta = theta.toDouble()
|
this.theta = theta.toDouble()
|
||||||
}.also { set(name, it) }
|
}.also { set(name, it) }
|
@ -1,16 +1,15 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
import hep.dataforge.output.Output
|
import hep.dataforge.output.Output
|
||||||
|
import hep.dataforge.vis.common.AbstractVisualObject
|
||||||
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.asName
|
import hep.dataforge.vis.common.asName
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.detailKey
|
import hep.dataforge.vis.spatial.VisualObject3D.Companion.DETAIL_KEY
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.materialKey
|
import hep.dataforge.vis.spatial.VisualObject3D.Companion.MATERIAL_KEY
|
||||||
import hep.dataforge.vis.spatial.VisualObject3D.Companion.visibleKey
|
import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY
|
||||||
|
|
||||||
data class Value3(var x: Float = 0f, var y: Float = 0f, var z: Float = 0f)
|
data class Value3(var x: Float = 0f, var y: Float = 0f, var z: Float = 0f)
|
||||||
|
|
||||||
@ -19,13 +18,22 @@ interface VisualObject3D : VisualObject {
|
|||||||
var rotation: Value3
|
var rotation: Value3
|
||||||
var scale: Value3
|
var scale: Value3
|
||||||
|
|
||||||
fun setProperty(name: Name, value: Any?)
|
fun MetaBuilder.updatePosition() {
|
||||||
fun getProperty(name: Name, inherit: Boolean = true): MetaItem<*>?
|
xPos to position.x
|
||||||
|
yPos to position.y
|
||||||
|
zPos to position.z
|
||||||
|
xRotation to rotation.x
|
||||||
|
yRotation to rotation.y
|
||||||
|
zRotation to rotation.z
|
||||||
|
xScale to scale.x
|
||||||
|
yScale to scale.y
|
||||||
|
zScale to scale.z
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val materialKey = "material".asName()
|
val MATERIAL_KEY = "material".asName()
|
||||||
val visibleKey = "visible".asName()
|
val VISIBLE_KEY = "visible".asName()
|
||||||
val detailKey = "detail".asName()
|
val DETAIL_KEY = "detail".asName()
|
||||||
|
|
||||||
val x = "x".asName()
|
val x = "x".asName()
|
||||||
val y = "y".asName()
|
val y = "y".asName()
|
||||||
@ -53,64 +61,32 @@ interface VisualObject3D : VisualObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class VisualLeaf3D(parent: VisualObject?, tagRefs: Array<out Meta>) : VisualLeaf(parent, tagRefs), VisualObject3D {
|
abstract class VisualLeaf3D(parent: VisualObject?) : AbstractVisualObject(parent), VisualObject3D, Configurable {
|
||||||
override var position: Value3 = Value3()
|
override var position: Value3 = Value3()
|
||||||
override var rotation: Value3 = Value3()
|
override var rotation: Value3 = Value3()
|
||||||
override var scale: Value3 = Value3(1f, 1f, 1f)
|
override var scale: Value3 = Value3(1f, 1f, 1f)
|
||||||
|
|
||||||
private var _config: Config? = null
|
|
||||||
override val config: Config get() = _config ?: Config().also { _config = it }
|
|
||||||
|
|
||||||
override fun setProperty(name: Name, value: Any?) {
|
|
||||||
config[name] = value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
class VisualGroup3D(parent: VisualObject? = null) : VisualGroup<VisualObject3D>(parent), VisualObject3D, Configurable {
|
||||||
return if (inherit) {
|
|
||||||
config[name] ?: (parent as? VisualObject3D)?.getProperty(name, inherit) ?: parent?.properties[name]
|
|
||||||
} else {
|
|
||||||
_config?.get(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VisualGroup3D(
|
|
||||||
parent: VisualObject? = null,
|
|
||||||
tagRefs: Array<out Meta> = emptyArray()
|
|
||||||
) : VisualGroup(parent, tagRefs), VisualObject3D {
|
|
||||||
|
|
||||||
override var position: Value3 = Value3()
|
override var position: Value3 = Value3()
|
||||||
override var rotation: Value3 = Value3()
|
override var rotation: Value3 = Value3()
|
||||||
override var scale: Value3 = Value3(1f, 1f, 1f)
|
override var scale: Value3 = Value3(1f, 1f, 1f)
|
||||||
|
|
||||||
private var _config: Config? = null
|
override fun MetaBuilder.updateMeta() {
|
||||||
override val config: Config get() = _config ?: Config().also { _config = it }
|
updatePosition()
|
||||||
|
updateChildren()
|
||||||
override fun setProperty(name: Name, value: Any?) {
|
|
||||||
config[name] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
|
||||||
return if (inherit) {
|
|
||||||
config[name] ?: (parent as? VisualObject3D)?.getProperty(name, inherit) ?: parent?.properties[name]
|
|
||||||
} else {
|
|
||||||
_config?.get(name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun VisualGroup3D.group(key: String? = null, action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
|
||||||
|
VisualGroup3D(this).apply(action).also { set(key, it) }
|
||||||
|
|
||||||
fun VisualGroup.group(key: String? = null, vararg meta: Meta, action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
|
fun Output<VisualObject3D>.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) =
|
||||||
VisualGroup3D(this, meta).apply(action).also { set(key, it) }
|
|
||||||
|
|
||||||
|
|
||||||
fun Output<VisualObject>.render(meta: Meta = EmptyMeta, action: VisualGroup3D.() -> Unit) =
|
|
||||||
render(VisualGroup3D().apply(action), meta)
|
render(VisualGroup3D().apply(action), meta)
|
||||||
|
|
||||||
|
|
||||||
// Common properties
|
// Common properties
|
||||||
|
|
||||||
|
|
||||||
enum class RotationOrder {
|
enum class RotationOrder {
|
||||||
XYZ,
|
XYZ,
|
||||||
YZX,
|
YZX,
|
||||||
@ -132,16 +108,16 @@ var VisualObject3D.rotationOrder: RotationOrder
|
|||||||
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default
|
* Preferred number of polygons for displaying the object. If not defined, uses shape or renderer default
|
||||||
*/
|
*/
|
||||||
var VisualObject3D.detail: Int?
|
var VisualObject3D.detail: Int?
|
||||||
get() = getProperty(detailKey).int
|
get() = getProperty(DETAIL_KEY).int
|
||||||
set(value) = setProperty(detailKey, value)
|
set(value) = setProperty(DETAIL_KEY, value)
|
||||||
|
|
||||||
var VisualObject3D.material: Meta?
|
var VisualObject3D.material: Meta?
|
||||||
get() = getProperty(materialKey).node
|
get() = getProperty(MATERIAL_KEY).node
|
||||||
set(value) = setProperty(materialKey, value)
|
set(value) = setProperty(MATERIAL_KEY, value)
|
||||||
|
|
||||||
var VisualObject3D.visible: Boolean?
|
var VisualObject3D.visible: Boolean?
|
||||||
get() = getProperty(visibleKey).boolean
|
get() = getProperty(VISIBLE_KEY).boolean
|
||||||
set(value) = setProperty(visibleKey, value)
|
set(value) = setProperty(VISIBLE_KEY, value)
|
||||||
|
|
||||||
fun VisualObject3D.color(rgb: Int) {
|
fun VisualObject3D.color(rgb: Int) {
|
||||||
material = buildMeta { "color" to rgb }
|
material = buildMeta { "color" to rgb }
|
||||||
@ -157,11 +133,66 @@ fun VisualObject3D.color(r: Int, g: Int, b: Int) = material {
|
|||||||
"blue" to b
|
"blue" to b
|
||||||
}
|
}
|
||||||
|
|
||||||
object World {
|
var VisualObject3D.x: Number
|
||||||
const val CAMERA_INITIAL_DISTANCE = -500.0
|
get() = position.x
|
||||||
const val CAMERA_INITIAL_X_ANGLE = -50.0
|
set(value) {
|
||||||
const val CAMERA_INITIAL_Y_ANGLE = 0.0
|
position.x = value.toFloat()
|
||||||
const val CAMERA_INITIAL_Z_ANGLE = -210.0
|
propertyChanged(VisualObject3D.xPos)
|
||||||
const val CAMERA_NEAR_CLIP = 0.1
|
|
||||||
const val CAMERA_FAR_CLIP = 10000.0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.y: Number
|
||||||
|
get() = position.y
|
||||||
|
set(value) {
|
||||||
|
position.y = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.yPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.z: Number
|
||||||
|
get() = position.z
|
||||||
|
set(value) {
|
||||||
|
position.z = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.zPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.rotationX: Number
|
||||||
|
get() = rotation.x
|
||||||
|
set(value) {
|
||||||
|
rotation.x = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.xRotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.rotationY: Number
|
||||||
|
get() = rotation.y
|
||||||
|
set(value) {
|
||||||
|
rotation.y = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.xRotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.rotationZ: Number
|
||||||
|
get() = rotation.z
|
||||||
|
set(value) {
|
||||||
|
rotation.z = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.zRotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.scaleX: Number
|
||||||
|
get() = scale.x
|
||||||
|
set(value) {
|
||||||
|
scale.x = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.xScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.scaleY: Number
|
||||||
|
get() = scale.y
|
||||||
|
set(value) {
|
||||||
|
scale.y = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.yScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
var VisualObject3D.scaleZ: Number
|
||||||
|
get() = scale.z
|
||||||
|
set(value) {
|
||||||
|
scale.z = value.toFloat()
|
||||||
|
propertyChanged(VisualObject3D.zScale)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
|
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,37 +0,0 @@
|
|||||||
package hep.dataforge.vis.spatial
|
|
||||||
|
|
||||||
var VisualObject3D.x: Number
|
|
||||||
get() = position.x
|
|
||||||
set(value) {position.x = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.y: Number
|
|
||||||
get() = position.y
|
|
||||||
set(value) {position.y = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.z: Number
|
|
||||||
get() = position.z
|
|
||||||
set(value) {position.z = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.rotationX: Number
|
|
||||||
get() = rotation.x
|
|
||||||
set(value) {rotation.x = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.rotationY: Number
|
|
||||||
get() = rotation.y
|
|
||||||
set(value) {rotation.y = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.rotationZ: Number
|
|
||||||
get() = rotation.z
|
|
||||||
set(value) {rotation.z = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.scaleX: Number
|
|
||||||
get() = scale.x
|
|
||||||
set(value) {scale.x = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.scaleY: Number
|
|
||||||
get() = scale.y
|
|
||||||
set(value) {scale.y = value.toFloat()}
|
|
||||||
|
|
||||||
var VisualObject3D.scaleZ: Number
|
|
||||||
get() = scale.z
|
|
||||||
set(value) {scale.z = value.toFloat()}
|
|
@ -4,14 +4,13 @@ import hep.dataforge.meta.get
|
|||||||
import hep.dataforge.meta.getAll
|
import hep.dataforge.meta.getAll
|
||||||
import hep.dataforge.meta.node
|
import hep.dataforge.meta.node
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class ConvexTest {
|
class ConvexTest {
|
||||||
@Test
|
@Test
|
||||||
fun testConvexBuilder() {
|
fun testConvexBuilder() {
|
||||||
val group = VisualGroup().apply {
|
val group = VisualNode().apply {
|
||||||
convex {
|
convex {
|
||||||
point(50, 50, -50)
|
point(50, 50, -50)
|
||||||
point(50, -50, -50)
|
point(50, -50, -50)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package hep.dataforge.vis.spatial
|
package hep.dataforge.vis.spatial
|
||||||
|
|
||||||
import hep.dataforge.vis.common.Colors
|
import hep.dataforge.vis.common.Colors
|
||||||
import hep.dataforge.vis.common.VisualGroup
|
|
||||||
import hep.dataforge.vis.common.color
|
import hep.dataforge.vis.common.color
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
@ -10,7 +9,7 @@ import kotlin.test.assertEquals
|
|||||||
class GroupTest {
|
class GroupTest {
|
||||||
@Test
|
@Test
|
||||||
fun testGroupWithComposite(){
|
fun testGroupWithComposite(){
|
||||||
val group = VisualGroup().apply{
|
val group = VisualNode().apply{
|
||||||
union {
|
union {
|
||||||
box(100, 100, 100) {
|
box(100, 100, 100) {
|
||||||
z = 100
|
z = 100
|
||||||
|
Loading…
Reference in New Issue
Block a user