Dev #24

Merged
altavir merged 12 commits from dev into master 2020-04-12 19:31:02 +03:00
26 changed files with 6086 additions and 137 deletions
Showing only changes of commit e19ec02ff3 - Show all commits

View File

@ -74,12 +74,41 @@ abstract class AbstractVisualGroup : AbstractVisualObject(),
* Add a static child. Statics could not be found by name, removed or replaced * Add a static child. Statics could not be found by name, removed or replaced
*/ */
protected open fun addStatic(child: VisualObject) = protected open fun addStatic(child: VisualObject) =
setChild(NameToken("@static(${child.hashCode()})"), child) set(NameToken("@static(${child.hashCode()})").asName(), child)
protected abstract fun createGroup(): AbstractVisualGroup
/**
* Set this node as parent for given node
*/
protected fun attach(child: VisualObject) {
if (child.parent == null) {
child.parent = this
} else if (child.parent !== this) {
error("Can't reassign existing parent for $child")
}
}
/** /**
* Recursively create a child group * Recursively create a child group
*/ */
protected abstract fun createGroup(name: Name): MutableVisualGroup private fun createGroups(name: Name): AbstractVisualGroup {
return when {
name.isEmpty() -> error("Should be unreachable")
name.length == 1 -> {
val token = name.first()!!
when (val current = children[token]) {
null -> createGroup().also { child ->
attach(child)
setChild(token, child)
}
is AbstractVisualGroup -> current
else -> error("Can't create group with name $name because it exists and not a group")
}
}
else -> createGroups(name.first()!!.asName()).createGroups(name.cutFirst())
}
}
/** /**
* Add named or unnamed child to the group. If key is null the child is considered unnamed. Both key and value are not * Add named or unnamed child to the group. If key is null the child is considered unnamed. Both key and value are not
@ -97,16 +126,17 @@ abstract class AbstractVisualGroup : AbstractVisualObject(),
if (child == null) { if (child == null) {
removeChild(token) removeChild(token)
} else { } else {
attach(child)
setChild(token, child) setChild(token, child)
} }
} }
else -> { else -> {
//TODO add safety check //TODO add safety check
val parent = (get(name.cutLast()) as? MutableVisualGroup) ?: createGroup(name.cutLast()) val parent = (get(name.cutLast()) as? MutableVisualGroup) ?: createGroups(name.cutLast())
parent[name.last()!!.asName()] = child parent[name.last()!!.asName()] = child
} }
} }
structureChangeListeners.forEach { it.callback(name, child) } childrenChanged(name, child)
} }
} }

View File

@ -15,7 +15,7 @@ internal data class PropertyListener(
abstract class AbstractVisualObject : VisualObject { abstract class AbstractVisualObject : VisualObject {
@Transient @Transient
override var parent: VisualObject? = null override var parent: VisualGroup? = null
protected abstract var properties: Config? protected abstract var properties: Config?

View File

@ -6,12 +6,14 @@ import hep.dataforge.meta.*
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName import hep.dataforge.names.asName
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.serializer
/** /**
* A container for styles * A container for styles
*/ */
@Serializable @Serializable
class StyleSheet() { class StyleSheet private constructor(private val styleMap: MutableMap<String, Meta> = LinkedHashMap()) {
@Transient @Transient
internal var owner: VisualObject? = null internal var owner: VisualObject? = null
@ -19,12 +21,10 @@ class StyleSheet() {
this.owner = owner this.owner = owner
} }
private val styleMap = HashMap<String, Meta>()
val items: Map<String, Meta> get() = styleMap val items: Map<String, Meta> get() = styleMap
operator fun get(key: String): Meta? { operator fun get(key: String): Meta? {
return styleMap[key] ?: (owner?.parent as? VisualGroup)?.styleSheet?.get(key) return styleMap[key] ?: owner?.parent?.styleSheet?.get(key)
} }
/** /**
@ -49,16 +49,19 @@ class StyleSheet() {
set(key, newStyle.seal()) set(key, newStyle.seal())
} }
companion object: KSerializer<StyleSheet>{ @Serializer(StyleSheet::class)
override val descriptor: SerialDescriptor companion object : KSerializer<StyleSheet> {
get() = TODO("Not yet implemented") private val mapSerializer = MapSerializer(String.serializer(), MetaSerializer)
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
override fun deserialize(decoder: Decoder): StyleSheet { override fun deserialize(decoder: Decoder): StyleSheet {
TODO("Not yet implemented") val map = mapSerializer.deserialize(decoder)
return StyleSheet(map as? MutableMap<String, Meta> ?: LinkedHashMap(map))
} }
override fun serialize(encoder: Encoder, value: StyleSheet) { override fun serialize(encoder: Encoder, value: StyleSheet) {
TODO("Not yet implemented") mapSerializer.serialize(encoder, value.items)
} }
} }

View File

@ -24,7 +24,7 @@ interface VisualObject : 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.
*/ */
@Transient @Transient
var parent: VisualObject? var parent: VisualGroup?
/** /**
* All properties including styles and prototypes if present, but without inheritance * All properties including styles and prototypes if present, but without inheritance

View File

@ -3,10 +3,11 @@ package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBuilder import hep.dataforge.meta.MetaBuilder
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.vis.useStyle
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY
import hep.dataforge.vis.useStyle
import scientifik.gdml.* import scientifik.gdml.*
import kotlin.random.Random import kotlin.random.Random
@ -68,7 +69,13 @@ class GDMLTransformer(val root: GDML) {
var onFinish: GDMLTransformer.() -> Unit = {} var onFinish: GDMLTransformer.() -> Unit = {}
internal fun finalize(final: VisualGroup3D): VisualGroup3D { internal fun finalize(final: VisualGroup3D): VisualGroup3D {
final.prototypes = proto //final.prototypes = proto
final.prototypes {
proto.children.forEach { (token, item) ->
item.parent = null
set(token.asName(), item)
}
}
styleCache.forEach { styleCache.forEach {
final.styleSheet { final.styleSheet {
define(it.key.toString(), it.value) define(it.key.toString(), it.value)

View File

@ -1,5 +1,6 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial.gdml
import hep.dataforge.meta.JSON_PRETTY
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.vis.spatial.* import hep.dataforge.vis.spatial.*
import kotlinx.serialization.* import kotlinx.serialization.*
@ -157,7 +158,7 @@ fun main() {
} }
println( println(
Json.indented.stringify( JSON_PRETTY.stringify(
JsonObjectSerializer, JsonObjectSerializer,
json { json {
"definitions" to definitions "definitions" to definitions

View File

@ -1,43 +1,29 @@
package hep.dataforge.vis.spatial.gdml package hep.dataforge.vis.spatial.gdml
import hep.dataforge.vis.spatial.stringify
import nl.adaptivity.xmlutil.StAXReader import nl.adaptivity.xmlutil.StAXReader
import org.junit.jupiter.api.Test import org.junit.jupiter.api.Test
import scientifik.gdml.GDML import scientifik.gdml.GDML
import java.io.File
import java.net.URL
import kotlin.test.Ignore
class TestConvertor { class TestConvertor {
@Test @Test
@Ignore
fun testBMNGeometry() { fun testBMNGeometry() {
val url = URL("https://drive.google.com/open?id=1w5e7fILMN83JGgB8WANJUYm8OW2s0WVO") val stream = javaClass.getResourceAsStream("/gdml/BM@N.gdml")
val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\BM@N.gdml")
val stream = if (file.exists()) {
file.inputStream()
} else {
url.openStream()
}
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
xml.toVisual()
}
@Test
@Ignore
fun testCubes() {
val file = File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml ")
val stream = if (file.exists()) {
file.inputStream()
} else {
return
}
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)
val visual = xml.toVisual() val visual = xml.toVisual()
println(visual) println(visual.stringify())
}
@Test
fun testCubes() {
val stream = javaClass.getResourceAsStream("/gdml/cubes.gdml")
val xmlReader = StAXReader(stream, "UTF-8")
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
val visual = xml.toVisual()
// println(visual)
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
<gdml>
<define>
<position name="center" x="0.0" y="0.0" z="0.0" unit="cm"/>
<position name="box_position" x="25.0" y="50.0" z="75.0" unit="cm"/>
<rotation name="Rot0" x="0.0" y="0.0" z="0.0" unit="deg"/>
<rotation name="Rot1" x="0.0" y="0.0" z="60.0" unit="deg"/>
<rotation name="Rot2" x="0.0" y="0.0" z="120.0" unit="deg"/>
<rotation name="Rot3" x="0.0" y="0.0" z="180.0" unit="deg"/>
<rotation name="Rot4" x="0.0" y="0.0" z="240.0" unit="deg"/>
<rotation name="Rot5" x="0.0" y="0.0" z="300.0" unit="deg"/>
<rotation name="Rot000" x="0.0" y="0.0" z="0.0" unit="deg"/>
<position name="Pos000" x="-50.0" y="-50.0" z="-50.0" unit="cm"/>
<rotation name="Rot001" x="0.0" y="0.0" z="120.0" unit="deg"/>
<position name="Pos001" x="-50.0" y="-50.0" z="0.0" unit="cm"/>
<rotation name="Rot002" x="0.0" y="0.0" z="240.0" unit="deg"/>
<position name="Pos002" x="-50.0" y="-50.0" z="50.0" unit="cm"/>
<rotation name="Rot010" x="0.0" y="120.0" z="0.0" unit="deg"/>
<position name="Pos010" x="-50.0" y="0.0" z="-50.0" unit="cm"/>
<rotation name="Rot011" x="0.0" y="120.0" z="120.0" unit="deg"/>
<position name="Pos011" x="-50.0" y="0.0" z="0.0" unit="cm"/>
<rotation name="Rot012" x="0.0" y="120.0" z="240.0" unit="deg"/>
<position name="Pos012" x="-50.0" y="0.0" z="50.0" unit="cm"/>
<rotation name="Rot020" x="0.0" y="240.0" z="0.0" unit="deg"/>
<position name="Pos020" x="-50.0" y="50.0" z="-50.0" unit="cm"/>
<rotation name="Rot021" x="0.0" y="240.0" z="120.0" unit="deg"/>
<position name="Pos021" x="-50.0" y="50.0" z="0.0" unit="cm"/>
<rotation name="Rot022" x="0.0" y="240.0" z="240.0" unit="deg"/>
<position name="Pos022" x="-50.0" y="50.0" z="50.0" unit="cm"/>
<rotation name="Rot100" x="120.0" y="0.0" z="0.0" unit="deg"/>
<position name="Pos100" x="0.0" y="-50.0" z="-50.0" unit="cm"/>
<rotation name="Rot101" x="120.0" y="0.0" z="120.0" unit="deg"/>
<position name="Pos101" x="0.0" y="-50.0" z="0.0" unit="cm"/>
<rotation name="Rot102" x="120.0" y="0.0" z="240.0" unit="deg"/>
<position name="Pos102" x="0.0" y="-50.0" z="50.0" unit="cm"/>
<rotation name="Rot110" x="120.0" y="120.0" z="0.0" unit="deg"/>
<position name="Pos110" x="0.0" y="0.0" z="-50.0" unit="cm"/>
<rotation name="Rot111" x="120.0" y="120.0" z="120.0" unit="deg"/>
<position name="Pos111" x="0.0" y="0.0" z="0.0" unit="cm"/>
<rotation name="Rot112" x="120.0" y="120.0" z="240.0" unit="deg"/>
<position name="Pos112" x="0.0" y="0.0" z="50.0" unit="cm"/>
<rotation name="Rot120" x="120.0" y="240.0" z="0.0" unit="deg"/>
<position name="Pos120" x="0.0" y="50.0" z="-50.0" unit="cm"/>
<rotation name="Rot121" x="120.0" y="240.0" z="120.0" unit="deg"/>
<position name="Pos121" x="0.0" y="50.0" z="0.0" unit="cm"/>
<rotation name="Rot122" x="120.0" y="240.0" z="240.0" unit="deg"/>
<position name="Pos122" x="0.0" y="50.0" z="50.0" unit="cm"/>
<rotation name="Rot200" x="240.0" y="0.0" z="0.0" unit="deg"/>
<position name="Pos200" x="50.0" y="-50.0" z="-50.0" unit="cm"/>
<rotation name="Rot201" x="240.0" y="0.0" z="120.0" unit="deg"/>
<position name="Pos201" x="50.0" y="-50.0" z="0.0" unit="cm"/>
<rotation name="Rot202" x="240.0" y="0.0" z="240.0" unit="deg"/>
<position name="Pos202" x="50.0" y="-50.0" z="50.0" unit="cm"/>
<rotation name="Rot210" x="240.0" y="120.0" z="0.0" unit="deg"/>
<position name="Pos210" x="50.0" y="0.0" z="-50.0" unit="cm"/>
<rotation name="Rot211" x="240.0" y="120.0" z="120.0" unit="deg"/>
<position name="Pos211" x="50.0" y="0.0" z="0.0" unit="cm"/>
<rotation name="Rot212" x="240.0" y="120.0" z="240.0" unit="deg"/>
<position name="Pos212" x="50.0" y="0.0" z="50.0" unit="cm"/>
<rotation name="Rot220" x="240.0" y="240.0" z="0.0" unit="deg"/>
<position name="Pos220" x="50.0" y="50.0" z="-50.0" unit="cm"/>
<rotation name="Rot221" x="240.0" y="240.0" z="120.0" unit="deg"/>
<position name="Pos221" x="50.0" y="50.0" z="0.0" unit="cm"/>
<rotation name="Rot222" x="240.0" y="240.0" z="240.0" unit="deg"/>
<position name="Pos222" x="50.0" y="50.0" z="50.0" unit="cm"/>
</define>
<materials/>
<solids>
<tube aunit="degree" name="segment" rmax="20.0" z="5.0" rmin="17.0" startphi="0.0" deltaphi="60.0"/>
<box name="cave" x="200.0" y="200.0" z="200.0"/>
<box name="box" x="30.0" y="30.0" z="30.0"/>
</solids>
<structure>
<volume name="segment_vol">
<materialref ref="G4_WATER"/>
<solidref ref="segment"/>
</volume>
<volume name="composite">
<physvol name="segment_0">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot0"/>
</physvol>
<physvol name="segment_1">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot1"/>
</physvol>
<physvol name="segment_2">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot2"/>
</physvol>
<physvol name="segment_3">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot3"/>
</physvol>
<physvol name="segment_4">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot4"/>
</physvol>
<physvol name="segment_5">
<volumeref ref="segment_vol"/>
<positionref ref="center"/>
<rotationref ref="Rot5"/>
</physvol>
<materialref ref="G4_AIR"/>
<solidref ref="box"/>
</volume>
<volume name="world">
<physvol name="composite_000">
<volumeref ref="composite"/>
<positionref ref="Pos000"/>
<rotationref ref="Rot000"/>
</physvol>
<physvol name="composite_001">
<volumeref ref="composite"/>
<positionref ref="Pos001"/>
<rotationref ref="Rot001"/>
</physvol>
<physvol name="composite_002">
<volumeref ref="composite"/>
<positionref ref="Pos002"/>
<rotationref ref="Rot002"/>
</physvol>
<physvol name="composite_003">
<volumeref ref="composite"/>
<positionref ref="Pos010"/>
<rotationref ref="Rot010"/>
</physvol>
<physvol name="composite_004">
<volumeref ref="composite"/>
<positionref ref="Pos011"/>
<rotationref ref="Rot011"/>
</physvol>
<physvol name="composite_005">
<volumeref ref="composite"/>
<positionref ref="Pos012"/>
<rotationref ref="Rot012"/>
</physvol>
<physvol name="composite_006">
<volumeref ref="composite"/>
<positionref ref="Pos020"/>
<rotationref ref="Rot020"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos021"/>
<rotationref ref="Rot021"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos022"/>
<rotationref ref="Rot022"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos100"/>
<rotationref ref="Rot100"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos101"/>
<rotationref ref="Rot101"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos102"/>
<rotationref ref="Rot102"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos110"/>
<rotationref ref="Rot110"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos111"/>
<rotationref ref="Rot111"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos112"/>
<rotationref ref="Rot112"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos120"/>
<rotationref ref="Rot120"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos121"/>
<rotationref ref="Rot121"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos122"/>
<rotationref ref="Rot122"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos200"/>
<rotationref ref="Rot200"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos201"/>
<rotationref ref="Rot201"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos202"/>
<rotationref ref="Rot202"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos210"/>
<rotationref ref="Rot210"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos211"/>
<rotationref ref="Rot211"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos212"/>
<rotationref ref="Rot212"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos220"/>
<rotationref ref="Rot220"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos221"/>
<rotationref ref="Rot221"/>
</physvol>
<physvol>
<volumeref ref="composite"/>
<positionref ref="Pos222"/>
<rotationref ref="Rot222"/>
</physvol>
<materialref ref="G4_AIR"/>
<solidref ref="cave"/>
</volume>
</structure>
<setup name="Default" version="1.0">
<world ref="world"/>
</setup>
</gdml>

View File

@ -6,10 +6,7 @@ import hep.dataforge.meta.Config
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.meta.float import hep.dataforge.meta.float
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.*
import hep.dataforge.vis.VisualFactory
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.set
import hep.dataforge.vis.spatial.Box.Companion.TYPE_NAME import hep.dataforge.vis.spatial.Box.Companion.TYPE_NAME
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -67,7 +64,7 @@ class Box(
} }
} }
inline fun VisualGroup3D.box( inline fun MutableVisualGroup.box(
xSize: Number, xSize: Number,
ySize: Number, ySize: Number,
zSize: Number, zSize: Number,

View File

@ -4,8 +4,8 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.meta.update import hep.dataforge.meta.update
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.names.NameToken
import hep.dataforge.vis.set import hep.dataforge.vis.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
@ -22,7 +22,7 @@ class Composite(
val compositeType: CompositeType, val compositeType: CompositeType,
val first: VisualObject3D, val first: VisualObject3D,
val second: VisualObject3D val second: VisualObject3D
) : AbstractVisualObject(), VisualObject3D { ) : AbstractVisualObject(), VisualObject3D, VisualGroup {
init { init {
first.parent = this first.parent = this
@ -34,9 +34,15 @@ class Composite(
override var scale: Point3D? = null override var scale: Point3D? = null
override var properties: Config? = null override var properties: Config? = null
override val children: Map<NameToken, VisualObject>
get() = mapOf(NameToken("first") to first, NameToken("second") to second)
override val styleSheet: StyleSheet?
get() = null
} }
inline fun VisualGroup3D.composite( inline fun MutableVisualGroup.composite(
type: CompositeType, type: CompositeType,
name: String = "", name: String = "",
builder: VisualGroup3D.() -> Unit builder: VisualGroup3D.() -> Unit
@ -48,24 +54,24 @@ inline fun VisualGroup3D.composite(
it.config.update(group.config) it.config.update(group.config)
//it.material = group.material //it.material = group.material
if(group.position!=null) { if (group.position != null) {
it.position = group.position it.position = group.position
} }
if(group.rotation!=null) { if (group.rotation != null) {
it.rotation = group.rotation it.rotation = group.rotation
} }
if(group.scale!=null) { if (group.scale != null) {
it.scale = group.scale it.scale = group.scale
} }
set(name, it) set(name, it)
} }
} }
fun VisualGroup3D.union(name: String = "", builder: VisualGroup3D.() -> Unit) = inline fun MutableVisualGroup.union(name: String = "", builder: VisualGroup3D.() -> Unit) =
composite(CompositeType.UNION, name, builder = builder) composite(CompositeType.UNION, name, builder = builder)
fun VisualGroup3D.subtract(name: String = "", builder: VisualGroup3D.() -> Unit) = inline fun MutableVisualGroup.subtract(name: String = "", builder: VisualGroup3D.() -> Unit) =
composite(CompositeType.SUBTRACT, name, builder = builder) composite(CompositeType.SUBTRACT, name, builder = builder)
fun VisualGroup3D.intersect(name: String = "", builder: VisualGroup3D.() -> Unit) = inline fun MutableVisualGroup.intersect(name: String = "", builder: VisualGroup3D.() -> Unit) =
composite(CompositeType.INTERSECT, name, builder = builder) composite(CompositeType.INTERSECT, name, builder = builder)

View File

@ -4,6 +4,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -74,7 +75,7 @@ class ConeSegment(
} }
inline fun VisualGroup3D.cylinder( inline fun MutableVisualGroup.cylinder(
r: Number, r: Number,
height: Number, height: Number,
name: String = "", name: String = "",
@ -86,7 +87,7 @@ inline fun VisualGroup3D.cylinder(
).apply(block).also { set(name, it) } ).apply(block).also { set(name, it) }
inline fun VisualGroup3D.cone( inline fun MutableVisualGroup.cone(
bottomRadius: Number, bottomRadius: Number,
height: Number, height: Number,
upperRadius: Number = 0.0, upperRadius: Number = 0.0,

View File

@ -4,6 +4,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -24,7 +25,7 @@ class Convex(val points: List<Point3D>) : AbstractVisualObject(), VisualObject3D
} }
} }
inline fun VisualGroup3D.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}) = inline fun MutableVisualGroup.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}) =
ConvexBuilder().apply(action).build().also { set(name, it) } ConvexBuilder().apply(action).build().also { set(name, it) }
class ConvexBuilder { class ConvexBuilder {

View File

@ -3,6 +3,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -111,5 +112,5 @@ class Extruded(
} }
} }
fun VisualGroup3D.extrude(name: String = "", action: Extruded.() -> Unit = {}) = fun MutableVisualGroup.extrude(name: String = "", action: Extruded.() -> Unit = {}) =
Extruded().apply(action).also { set(name, it) } Extruded().apply(action).also { set(name, it) }

View File

@ -4,6 +4,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -20,7 +21,7 @@ class Label3D(var text: String, var fontSize: Double, var fontFamily: String) :
} }
fun VisualGroup3D.label( fun MutableVisualGroup.label(
text: String, text: String,
fontSize: Number = 20, fontSize: Number = 20,
fontFamily: String = "Arial", fontFamily: String = "Arial",

View File

@ -7,6 +7,7 @@ import hep.dataforge.meta.number
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.plus import hep.dataforge.names.plus
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -30,5 +31,5 @@ class PolyLine(var points: List<Point3D>) : AbstractVisualObject(), VisualObject
} }
fun VisualGroup3D.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) = fun MutableVisualGroup.polyline(vararg points: Point3D, name: String = "", action: PolyLine.() -> Unit = {}) =
PolyLine(points.toList()).apply(action).also { set(name, it) } PolyLine(points.toList()).apply(action).also { set(name, it) }

View File

@ -6,10 +6,7 @@ import hep.dataforge.meta.Config
import hep.dataforge.meta.Laminate import hep.dataforge.meta.Laminate
import hep.dataforge.meta.MetaItem import hep.dataforge.meta.MetaItem
import hep.dataforge.meta.get import hep.dataforge.meta.get
import hep.dataforge.names.Name import hep.dataforge.names.*
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import hep.dataforge.vis.* import hep.dataforge.vis.*
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -24,8 +21,9 @@ import kotlin.collections.set
*/ */
@Serializable @Serializable
@SerialName("3d.proxy") @SerialName("3d.proxy")
class Proxy private constructor(val templateName: Name) : AbstractVisualObject(), class Proxy private constructor(
VisualGroup, VisualObject3D { val templateName: Name
) : AbstractVisualObject(), VisualGroup, VisualObject3D {
constructor(parent: VisualGroup3D, templateName: Name) : this(templateName) { constructor(parent: VisualGroup3D, templateName: Name) : this(templateName) {
this.parent = parent this.parent = parent
@ -42,10 +40,10 @@ class Proxy private constructor(val templateName: Name) : AbstractVisualObject()
*/ */
val prototype: VisualObject3D val prototype: VisualObject3D
get() = (parent as? VisualGroup3D)?.getPrototype(templateName) get() = (parent as? VisualGroup3D)?.getPrototype(templateName)
?: error("Template with name $templateName not found in $parent") ?: error("Prototype with name $templateName not found in $parent")
override val styleSheet: StyleSheet override val styleSheet: StyleSheet
get() = (parent as? VisualGroup)?.styleSheet ?: StyleSheet( get() = parent?.styleSheet ?: StyleSheet(
this this
) )
@ -166,9 +164,9 @@ inline fun VisualGroup3D.ref(
* Add new proxy wrapping given object and automatically adding it to the prototypes * Add new proxy wrapping given object and automatically adding it to the prototypes
*/ */
fun VisualGroup3D.proxy( fun VisualGroup3D.proxy(
templateName: Name, name: String,
obj: VisualObject3D, obj: VisualObject3D,
name: String = "", templateName: Name = name.toName(),
block: Proxy.() -> Unit = {} block: Proxy.() -> Unit = {}
): Proxy { ): Proxy {
val existing = getPrototype(templateName) val existing = getPrototype(templateName)

View File

@ -4,6 +4,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -59,7 +60,7 @@ class Sphere(
} }
} }
inline fun VisualGroup3D.sphere( inline fun MutableVisualGroup.sphere(
radius: Number, radius: Number,
phi: Number = 2 * PI, phi: Number = 2 * PI,
theta: Number = PI, theta: Number = PI,

View File

@ -3,6 +3,7 @@ package hep.dataforge.vis.spatial
import hep.dataforge.meta.Config import hep.dataforge.meta.Config
import hep.dataforge.vis.AbstractVisualObject import hep.dataforge.vis.AbstractVisualObject
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.set import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -127,7 +128,7 @@ class Tube(
} }
inline fun VisualGroup3D.tube( inline fun MutableVisualGroup.tube(
r: Number, r: Number,
height: Number, height: Number,
innerRadius: Number = 0f, innerRadius: Number = 0f,

View File

@ -8,22 +8,23 @@ import hep.dataforge.meta.Config
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.names.asName import hep.dataforge.names.asName
import hep.dataforge.names.isEmpty import hep.dataforge.vis.*
import hep.dataforge.vis.AbstractVisualGroup
import hep.dataforge.vis.StyleSheet
import hep.dataforge.vis.VisualObject
import hep.dataforge.vis.set
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers import kotlinx.serialization.UseSerializers
import kotlin.collections.set import kotlin.collections.set
interface PrototypeHolder {
val parent: VisualGroup?
val prototypes: MutableVisualGroup?
}
/** /**
* Represents 3-dimensional Visual Group * Represents 3-dimensional Visual Group
*/ */
@Serializable @Serializable
@SerialName("group.3d") @SerialName("group.3d")
class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { class VisualGroup3D : AbstractVisualGroup(), VisualObject3D, PrototypeHolder {
override var styleSheet: StyleSheet? = null override var styleSheet: StyleSheet? = null
private set private set
@ -31,11 +32,19 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
/** /**
* A container for templates visible inside this group * A container for templates visible inside this group
*/ */
var prototypes: VisualGroup3D? = null @Serializable(PrototypesSerializer::class)
set(value) { override var prototypes: MutableVisualGroup? = null
value?.parent = this private set
field = value
} /**
* Create or edit prototype node as a group
*/
fun prototypes(builder: MutableVisualGroup.() -> Unit): Unit {
(prototypes ?: Prototypes().also {
attach(it)
prototypes = it
}).run(builder)
}
//FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed //FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
override var properties: Config? = null override var properties: Config? = null
@ -48,11 +57,6 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
private val _children = HashMap<NameToken, VisualObject>() private val _children = HashMap<NameToken, VisualObject>()
override val children: Map<NameToken, VisualObject> get() = _children override val children: Map<NameToken, VisualObject> get() = _children
// init {
// //Do after deserialization
// attachChildren()
// }
override fun attachChildren() { override fun attachChildren() {
prototypes?.parent = this prototypes?.parent = this
prototypes?.attachChildren() prototypes?.attachChildren()
@ -68,18 +72,11 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
} }
override fun removeChild(token: NameToken) { override fun removeChild(token: NameToken) {
_children.remove(token)?.run { parent = null } _children.remove(token)?.apply { parent = null }
childrenChanged(token.asName(), null)
} }
override fun setChild(token: NameToken, child: VisualObject) { override fun setChild(token: NameToken, child: VisualObject) {
if (child.parent == null) {
child.parent = this
} else if (child.parent !== this) {
error("Can't reassign existing parent for $child")
}
_children[token] = child _children[token] = child
childrenChanged(token.asName(), child)
} }
// /** // /**
@ -87,47 +84,72 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D {
// */ // */
// override fun addStatic(child: VisualObject) = setChild(NameToken("@static(${child.hashCode()})"), child) // override fun addStatic(child: VisualObject) = setChild(NameToken("@static(${child.hashCode()})"), child)
override fun createGroup(name: Name): VisualGroup3D { override fun createGroup(): VisualGroup3D = VisualGroup3D()
return when {
name.isEmpty() -> error("Should be unreachable") // return when {
name.length == 1 -> { // name.isEmpty() -> error("Should be unreachable")
val token = name.first()!! // name.length == 1 -> {
when (val current = children[token]) { // val token = name.first()!!
null -> VisualGroup3D().also { setChild(token, it) } // when (val current = children[token]) {
is VisualGroup3D -> current // null -> VisualGroup3D().also { setChild(token, it) }
else -> error("Can't create group with name $name because it exists and not a group") // is VisualGroup3D -> current
} // else -> error("Can't create group with name $name because it exists and not a group")
} // }
else -> createGroup(name.first()!!.asName()).createGroup(name.cutFirst()) // }
} // else -> createGroup(name.first()!!.asName()).createGroup(name.cutFirst())
} // }
// }
companion object { companion object {
// val PROTOTYPES_KEY = NameToken("@prototypes") // val PROTOTYPES_KEY = NameToken("@prototypes")
fun fromJson(json: String): VisualGroup3D = fun parseJson(json: String): VisualGroup3D =
Visual3D.json.parse(serializer(), json).also { it.attachChildren() } Visual3D.json.parse(serializer(), json).also { it.attachChildren() }
} }
} }
fun VisualGroup3D.stringify(): String = Visual3D.json.stringify(VisualGroup3D.serializer(),this)
/** /**
* Ger a prototype redirecting the request to the parent if prototype is not found * Ger a prototype redirecting the request to the parent if prototype is not found
*/ */
tailrec fun VisualGroup3D.getPrototype(name: Name): VisualObject3D? = tailrec fun PrototypeHolder.getPrototype(name: Name): VisualObject3D? =
prototypes?.get(name) as? VisualObject3D ?: (parent as? VisualGroup3D)?.getPrototype(name) prototypes?.get(name) as? VisualObject3D ?: (parent as? VisualGroup3D)?.getPrototype(name)
/**
* Create or edit prototype node as a group
*/
inline fun VisualGroup3D.prototypes(builder: VisualGroup3D.() -> Unit): Unit {
(prototypes ?: VisualGroup3D().also { prototypes = it }).run(builder)
}
/** /**
* Define a group with given [name], attach it to this parent and return it. * Define a group with given [name], attach it to this parent and return it.
*/ */
fun VisualGroup3D.group(name: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D = fun MutableVisualGroup.group(name: String = "", action: VisualGroup3D.() -> Unit = {}): VisualGroup3D =
VisualGroup3D().apply(action).also { VisualGroup3D().apply(action).also {
set(name, it) set(name, it)
} }
internal class Prototypes(
override var children: MutableMap<NameToken, VisualObject> = LinkedHashMap()
) : AbstractVisualGroup(), MutableVisualGroup, PrototypeHolder {
override val styleSheet: StyleSheet? get() = null
override fun removeChild(token: NameToken) {
children.remove(token)
childrenChanged(token.asName(), null)
}
override fun setChild(token: NameToken, child: VisualObject) {
children[token] = child
}
override fun createGroup(): Prototypes = Prototypes()
override var properties: Config? = null
override val prototypes: MutableVisualGroup get() = this
override fun attachChildren() {
children.values.forEach {
it.parent = parent
(it as? VisualGroup)?.attachChildren()
}
}
}

View File

@ -1,7 +1,11 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.meta.double import hep.dataforge.meta.double
import hep.dataforge.names.NameToken
import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.VisualObject
import kotlinx.serialization.* import kotlinx.serialization.*
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer import kotlinx.serialization.builtins.serializer
@ -90,4 +94,25 @@ object Point2DSerializer : KSerializer<Point2D> {
if (value.y != 0.0) encodeDoubleElement(descriptor, 1, value.y) if (value.y != 0.0) encodeDoubleElement(descriptor, 1, value.y)
} }
} }
}
@Serializer(MutableVisualGroup::class)
internal object PrototypesSerializer : KSerializer<MutableVisualGroup> {
private val mapSerializer: KSerializer<Map<NameToken, VisualObject>> =
MapSerializer(
NameToken.serializer(),
PolymorphicSerializer(VisualObject::class)
)
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
override fun deserialize(decoder: Decoder): MutableVisualGroup {
val map = mapSerializer.deserialize(decoder)
return Prototypes(map as? MutableMap<NameToken, VisualObject> ?: LinkedHashMap(map))
}
override fun serialize(encoder: Encoder, value: MutableVisualGroup) {
mapSerializer.serialize(encoder, value.children)
}
} }

View File

@ -6,7 +6,6 @@ import hep.dataforge.vis.MutableVisualGroup
import hep.dataforge.vis.VisualGroup import hep.dataforge.vis.VisualGroup
import hep.dataforge.vis.spatial.Proxy import hep.dataforge.vis.spatial.Proxy
import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualGroup3D
import hep.dataforge.vis.spatial.prototypes
object UnRef : VisualTreeTransform<VisualGroup3D>() { object UnRef : VisualTreeTransform<VisualGroup3D>() {
private fun VisualGroup.countRefs(): Map<Name, Int> { private fun VisualGroup.countRefs(): Map<Name, Int> {

View File

@ -1,12 +1,11 @@
package hep.dataforge.vis.spatial package hep.dataforge.vis.spatial
import hep.dataforge.vis.get
import hep.dataforge.vis.spatial.Visual3D.Companion.json import hep.dataforge.vis.spatial.Visual3D.Companion.json
import kotlinx.serialization.ImplicitReflectionSerializer
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
class SerializationTest { class SerializationTest {
@ImplicitReflectionSerializer
@Test @Test
fun testCubeSerialization() { fun testCubeSerialization() {
val cube = Box(100f, 100f, 100f).apply { val cube = Box(100f, 100f, 100f).apply {
@ -19,4 +18,21 @@ class SerializationTest {
val newCube = json.parse(Box.serializer(), string) val newCube = json.parse(Box.serializer(), string)
assertEquals(cube.config, newCube.config) assertEquals(cube.config, newCube.config)
} }
@Test
fun testProxySerialization() {
val cube = Box(100f, 100f, 100f).apply {
color(222)
x = 100
z = -100
}
val group = VisualGroup3D().apply {
proxy("cube", cube)
}
val string = group.stringify()
println(string)
val reconstructed = VisualGroup3D.parseJson(string)
assertEquals(group["cube"]?.config, reconstructed["cube"]?.config)
}
} }

View File

@ -3,8 +3,6 @@ package hep.dataforge.vis.spatial.gdml.demo
import hep.dataforge.context.Global import hep.dataforge.context.Global
import hep.dataforge.js.Application import hep.dataforge.js.Application
import hep.dataforge.js.startApplication import hep.dataforge.js.startApplication
import hep.dataforge.meta.Meta
import hep.dataforge.meta.withBottom
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty import hep.dataforge.names.isEmpty
import hep.dataforge.vis.VisualGroup import hep.dataforge.vis.VisualGroup
@ -23,7 +21,6 @@ import hep.dataforge.vis.spatial.gdml.toVisual
import hep.dataforge.vis.spatial.three.ThreePlugin import hep.dataforge.vis.spatial.three.ThreePlugin
import hep.dataforge.vis.spatial.three.displayCanvasControls import hep.dataforge.vis.spatial.three.displayCanvasControls
import hep.dataforge.vis.spatial.three.output import hep.dataforge.vis.spatial.three.output
import hep.dataforge.vis.spatial.visible
import org.w3c.dom.* import org.w3c.dom.*
import org.w3c.files.FileList import org.w3c.files.FileList
import org.w3c.files.FileReader import org.w3c.files.FileReader
@ -139,7 +136,7 @@ private class GDMLDemoApp : Application {
message("Converting GDML into DF-VIS format") message("Converting GDML into DF-VIS format")
gdml.toVisual(gdmlConfiguration) gdml.toVisual(gdmlConfiguration)
} }
name.endsWith(".json") -> VisualGroup3D.fromJson(data) name.endsWith(".json") -> VisualGroup3D.parseJson(data)
else -> { else -> {
window.alert("File extension is not recognized: $name") window.alert("File extension is not recognized: $name")
error("File extension is not recognized: $name") error("File extension is not recognized: $name")

View File

@ -30,19 +30,19 @@ fun Visual3D.Companion.readFile(file: File): VisualGroup3D = when {
} }
} }
} }
file.extension == "json" -> VisualGroup3D.fromJson(file.readText()) file.extension == "json" -> VisualGroup3D.parseJson(file.readText())
file.name.endsWith("json.zip") -> { file.name.endsWith("json.zip") -> {
file.inputStream().use { file.inputStream().use {
val unzip = ZipInputStream(it, Charsets.UTF_8) val unzip = ZipInputStream(it, Charsets.UTF_8)
val text = unzip.readAllBytes().decodeToString() val text = unzip.readAllBytes().decodeToString()
VisualGroup3D.fromJson(text) VisualGroup3D.parseJson(text)
} }
} }
file.name.endsWith("json.gz") -> { file.name.endsWith("json.gz") -> {
file.inputStream().use { file.inputStream().use {
val unzip = GZIPInputStream(it) val unzip = GZIPInputStream(it)
val text = unzip.readAllBytes().decodeToString() val text = unzip.readAllBytes().decodeToString()
VisualGroup3D.fromJson(text) VisualGroup3D.parseJson(text)
} }
} }
else -> error("Unknown extension ${file.extension}") else -> error("Unknown extension ${file.extension}")

View File

@ -9,7 +9,7 @@ class FileSerializationTest {
@Ignore @Ignore
fun testFileRead(){ fun testFileRead(){
val text = this::class.java.getResourceAsStream("/cubes.json").readAllBytes().decodeToString() val text = this::class.java.getResourceAsStream("/cubes.json").readAllBytes().decodeToString()
val visual = VisualGroup3D.fromJson(text) val visual = VisualGroup3D.parseJson(text)
visual["composite_001".asName()] visual["composite_001".asName()]
} }
} }