diff --git a/dataforge-vis-spatial-gdml/build.gradle.kts b/dataforge-vis-spatial-gdml/build.gradle.kts index 2d8a4200..a1a23902 100644 --- a/dataforge-vis-spatial-gdml/build.gradle.kts +++ b/dataforge-vis-spatial-gdml/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { val commonMain by getting { dependencies { api(project(":dataforge-vis-spatial")) - api("scientifik:gdml:0.1.4") + api("scientifik:gdml:0.1.5") } } } diff --git a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt index 8fc395e1..26e1ef98 100644 --- a/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt +++ b/dataforge-vis-spatial-gdml/src/commonMain/kotlin/hep/dataforge/vis/spatial/gdml/visualGDML.kt @@ -66,6 +66,12 @@ private fun VisualGroup3D.addSolid( solid.deltaphi * aScale, name ) + is GDMLCone -> cone(solid.rmax1, solid.z, solid.rmax2, name = name) { + require(solid.rmin1 == 0.0){"Empty cones are not supported"} + require(solid.rmin2 == 0.0){"Empty cones are not supported"} + startAngle = solid.startphi.toFloat() + angle = solid.deltaphi.toFloat() + } is GDMLXtru -> extrude(name) { shape { solid.vertices.forEach { diff --git a/dataforge-vis-spatial/build.gradle.kts b/dataforge-vis-spatial/build.gradle.kts index 2fe2ac14..f587d39d 100644 --- a/dataforge-vis-spatial/build.gradle.kts +++ b/dataforge-vis-spatial/build.gradle.kts @@ -20,7 +20,7 @@ kotlin { } jvmMain { dependencies { - implementation("org.fxyz3d:fxyz3d:0.5.2") { + api("org.fxyz3d:fxyz3d:0.5.2") { exclude(module = "slf4j-simple") } api("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:${Scientifik.coroutinesVersion}") diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt index 9aa090ef..86abbe61 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/ConeSegment.kt @@ -82,4 +82,17 @@ inline fun VisualGroup3D.cylinder( r.toFloat(), height.toFloat(), r.toFloat() +).apply(block).also { set(name, it) } + + +inline fun VisualGroup3D.cone( + bottomRadius: Number, + height: Number, + upperRadius: Number = 0.0, + name: String = "", + block: ConeSegment.() -> Unit = {} +): ConeSegment = ConeSegment( + bottomRadius.toFloat(), + height.toFloat(), + upperRadius = upperRadius.toFloat() ).apply(block).also { set(name, it) } \ No newline at end of file diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt index 44717f4d..83a089a8 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/VisualGroup3D.kt @@ -54,10 +54,10 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { private val _children = HashMap() override val children: Map get() = _children - init { - //Do after deserialization - attachChildren() - } +// init { +// //Do after deserialization +// attachChildren() +// } /** * Update or create stylesheet @@ -103,15 +103,18 @@ class VisualGroup3D : AbstractVisualGroup(), VisualObject3D { } override fun attachChildren() { - super.attachChildren() - prototypes?.run { - parent = this - attachChildren() + prototypes?.let { + it.parent = this + it.attachChildren() } + super.attachChildren() } companion object { const val PROTOTYPES_KEY = "templates" + + fun fromJson(json: String): VisualGroup3D = + Visual3DPlugin.json.parse(serializer(),json).also { it.attachChildren() } } } diff --git a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt index b4f87d39..37115129 100644 --- a/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt +++ b/dataforge-vis-spatial/src/commonMain/kotlin/hep/dataforge/vis/spatial/serialization.kt @@ -46,8 +46,8 @@ object Point3DSerializer : KSerializer { when (val i = decodeElementIndex(descriptor)) { CompositeDecoder.READ_DONE -> break@loop 0 -> x = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 - 1 -> y = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 - 2 -> z = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 + 1 -> y = decodeNullableSerializableElement(descriptor, 1, DoubleSerializer.nullable) ?: 0.0 + 2 -> z = decodeNullableSerializableElement(descriptor, 2, DoubleSerializer.nullable) ?: 0.0 else -> throw SerializationException("Unknown index $i") } } @@ -79,7 +79,7 @@ object Point2DSerializer : KSerializer { when (val i = decodeElementIndex(descriptor)) { CompositeDecoder.READ_DONE -> break@loop 0 -> x = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 - 1 -> y = decodeNullableSerializableElement(descriptor, 0, DoubleSerializer.nullable) ?: 0.0 + 1 -> y = decodeNullableSerializableElement(descriptor, 1, DoubleSerializer.nullable) ?: 0.0 else -> throw SerializationException("Unknown index $i") } } diff --git a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt index 396d43b2..1d9c1a04 100644 --- a/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt +++ b/dataforge-vis-spatial/src/jvmMain/kotlin/hep/dataforge/vis/spatial/geometryJVM.kt @@ -1,12 +1,13 @@ package hep.dataforge.vis.spatial +import org.fxyz3d.geometry.Point3D as FXPoint3D actual data class Point2D(actual var x: Double, actual var y: Double) { actual constructor(x: Number, y: Number) : this(x.toDouble(), y.toDouble()) } -actual class Point3D(val point: org.fxyz3d.geometry.Point3D) { +actual class Point3D(val point: FXPoint3D) { actual constructor(x: Number, y: Number, z: Number) : this( - org.fxyz3d.geometry.Point3D( + FXPoint3D( x.toFloat(), y.toFloat(), z.toFloat() @@ -32,7 +33,7 @@ actual class Point3D(val point: org.fxyz3d.geometry.Point3D) { } override fun equals(other: Any?): Boolean { - return this.point == (other as? hep.dataforge.vis.spatial.Point3D)?.point + return this.point == (other as? Point3D)?.point } override fun hashCode(): Int { diff --git a/demo/gdml/build.gradle.kts b/demo/gdml/build.gradle.kts index 67570e1d..7558d178 100644 --- a/demo/gdml/build.gradle.kts +++ b/demo/gdml/build.gradle.kts @@ -27,6 +27,11 @@ kotlin { api(project(":dataforge-vis-spatial-gdml")) } } + jvmMain{ + dependencies { + api("org.fxyz3d:fxyz3d:0.5.2") + } + } } } diff --git a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt index f4e6d4c5..92ab0f6f 100644 --- a/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt +++ b/demo/gdml/src/jsMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/GDMLDemoApp.kt @@ -14,7 +14,6 @@ import hep.dataforge.vis.js.editor.displayPropertyEditor import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_COLOR_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_OPACITY_KEY import hep.dataforge.vis.spatial.Material3D.Companion.MATERIAL_WIREFRAME_KEY -import hep.dataforge.vis.spatial.Visual3DPlugin import hep.dataforge.vis.spatial.VisualGroup3D import hep.dataforge.vis.spatial.VisualObject3D import hep.dataforge.vis.spatial.VisualObject3D.Companion.VISIBLE_KEY @@ -142,9 +141,7 @@ private class GDMLDemoApp : Application { val visual: VisualObject3D = when { name.endsWith(".gdml") || name.endsWith(".xml") -> gdml.toVisual(gdmlConfiguration) - name.endsWith(".json") -> { - Visual3DPlugin.json.parse(VisualGroup3D.serializer(), data).apply { attachChildren() } - } + name.endsWith(".json") -> VisualGroup3D.fromJson(data) else -> { window.alert("File extension is not recognized: $name") error("File extension is not recognized: $name") diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt index 11c4e162..e4d66bdc 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/readFile.kt @@ -28,20 +28,19 @@ fun Visual3DPlugin.Companion.readFile(file: File): VisualGroup3D = when { } } } - file.extension == "json" -> Visual3DPlugin.json - .parse(VisualGroup3D.serializer(), file.readText()) + file.extension == "json" -> VisualGroup3D.fromJson(file.readText()) file.name.endsWith("json.zip") -> { file.inputStream().use { val unzip = ZipInputStream(it, Charsets.UTF_8) val text = unzip.readAllBytes().decodeToString() - json.parse(VisualGroup3D.serializer(), text) + VisualGroup3D.fromJson(text) } } file.name.endsWith("json.gz") -> { file.inputStream().use { val unzip = GZIPInputStream(it) val text = unzip.readAllBytes().decodeToString() - json.parse(VisualGroup3D.serializer(), text) + VisualGroup3D.fromJson(text) } } else -> error("Unknown extension ${file.extension}") diff --git a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt index 09ab2053..3f60546f 100644 --- a/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt +++ b/demo/gdml/src/jvmMain/kotlin/hep/dataforge/vis/spatial/gdml/demo/saveToJson.kt @@ -10,10 +10,10 @@ import java.io.File import java.nio.file.Paths fun main() { - val gdml = GDML.readFile(Paths.get("D:\\Work\\Projects\\gdml.kt\\gdml-source\\BM@N.gdml")) + val gdml = GDML.readFile(Paths.get("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.gdml")) val visual = gdml.toVisual { lUnit = LUnit.CM } val json = Visual3DPlugin.json.stringify(VisualGroup3D.serializer(), visual) - File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\BM@N.json").writeText(json) + File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json) } \ No newline at end of file diff --git a/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/FileSerializationTest.kt b/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/FileSerializationTest.kt new file mode 100644 index 00000000..c3a69cfb --- /dev/null +++ b/demo/gdml/src/jvmTest/kotlin/hep/dataforge/vis/spatial/FileSerializationTest.kt @@ -0,0 +1,13 @@ +package hep.dataforge.vis.spatial + +import hep.dataforge.names.asName +import org.junit.Test + +class FileSerializationTest { + @Test + fun testFileRead(){ + val text = this::class.java.getResourceAsStream("/cubes.json").readAllBytes().decodeToString() + val visual = VisualGroup3D.fromJson(text) + visual["composite_001".asName()] + } +} \ No newline at end of file diff --git a/demo/gdml/src/jvmTest/resources/cubes.json b/demo/gdml/src/jvmTest/resources/cubes.json new file mode 100644 index 00000000..31cbf7ba --- /dev/null +++ b/demo/gdml/src/jvmTest/resources/cubes.json @@ -0,0 +1,458 @@ +{ + "templates": { + "children": { + "segment": { + "type": "hep.dataforge.vis.spatial.Tube", + "radius": 20.0, + "height": 5.0, + "innerRadius": 17.0, + "angle": 1.0471976, + "properties": { + "@style": "material[G4_WATER]" + } + }, + "cave": { + "type": "3d.box", + "xSize": 200.0, + "ySize": 200.0, + "zSize": 200.0, + "properties": { + "@style": [ + "material[G4_AIR]", + "opaque" + ] + } + }, + "volumes": { + "type": "group.3d", + "children": { + "composite": { + "type": "group.3d", + "children": { + "segment_1": { + "type": "3d.proxy", + "templateName": "volumes.segment_vol", + "rotation": { + "z": 1.0471975803375244 + } + }, + "segment_2": { + "type": "3d.proxy", + "templateName": "volumes.segment_vol", + "rotation": { + "z": 2.094395160675049 + } + }, + "segment_3": { + "type": "3d.proxy", + "templateName": "volumes.segment_vol", + "rotation": { + "z": 3.1415927410125732 + } + }, + "segment_4": { + "type": "3d.proxy", + "templateName": "volumes.segment_vol", + "rotation": { + "z": 4.188790321350098 + } + }, + "segment_0": { + "type": "3d.proxy", + "templateName": "volumes.segment_vol" + }, + "box": { + "type": "3d.proxy", + "templateName": "box" + }, + "segment_5": { + "type": "3d.proxy", + "templateName": "volumes.segment_vol", + "rotation": { + "z": 5.235987663269043 + } + } + } + }, + "segment_vol": { + "type": "group.3d", + "children": { + "segment": { + "type": "3d.proxy", + "templateName": "segment" + } + } + } + } + }, + "box": { + "type": "3d.box", + "xSize": 30.0, + "ySize": 30.0, + "zSize": 30.0, + "properties": { + "@style": [ + "material[G4_AIR]", + "opaque" + ] + } + } + } + }, + "styleSheet": { + "styleMap": { + "material[G4_WATER]": { + "material": { + "color": 1710240 + }, + "gdml": { + "material": "G4_WATER" + } + }, + "opaque": { + "material": { + "opacity": 0.3 + } + }, + "material[G4_AIR]": { + "material": { + "color": 6376463 + }, + "gdml": { + "material": "G4_AIR" + } + } + } + }, + "properties": { + "rotation": { + "order": "ZXY" + } + }, + "children": { + "@static(1529060733)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "y": 50.0 + }, + "rotation": { + "x": 2.094395160675049, + "y": 4.188790321350098, + "z": 2.094395160675049 + } + }, + "@static(1496355635)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "rotation": { + "x": 2.094395160675049, + "y": 2.094395160675049, + "z": 2.094395160675049 + } + }, + "@static(166794956)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "y": -50.0 + }, + "rotation": { + "x": 2.094395160675049, + "z": 2.094395160675049 + } + }, + "@static(609962972)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "y": 50.0 + }, + "rotation": { + "x": 4.188790321350098, + "y": 4.188790321350098, + "z": 2.094395160675049 + } + }, + "@static(1741979653)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "y": -50.0, + "z": -50.0 + }, + "rotation": { + "x": 2.094395160675049 + } + }, + "@static(1484171695)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "z": 50.0 + }, + "rotation": { + "x": 2.094395160675049, + "y": 2.094395160675049, + "z": 4.188790321350098 + } + }, + "composite_003": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "z": -50.0 + }, + "rotation": { + "y": 2.094395160675049 + } + }, + "@static(6519275)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "y": 50.0 + }, + "rotation": { + "y": 4.188790321350098, + "z": 2.094395160675049 + } + }, + "composite_001": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "y": -50.0 + }, + "rotation": { + "z": 2.094395160675049 + } + }, + "@static(934275857)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0 + }, + "rotation": { + "x": 4.188790321350098, + "y": 2.094395160675049, + "z": 2.094395160675049 + } + }, + "composite_005": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "z": 50.0 + }, + "rotation": { + "y": 2.094395160675049, + "z": 4.188790321350098 + } + }, + "@static(712609105)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "y": -50.0 + }, + "rotation": { + "x": 4.188790321350098, + "z": 2.094395160675049 + } + }, + "@static(1364913072)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "z": 50.0 + }, + "rotation": { + "x": 4.188790321350098, + "y": 2.094395160675049, + "z": 4.188790321350098 + } + }, + "@static(232307208)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "y": 50.0, + "z": -50.0 + }, + "rotation": { + "x": 4.188790321350098, + "y": 4.188790321350098 + } + }, + "@static(1388278453)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "z": -50.0 + }, + "rotation": { + "x": 4.188790321350098, + "y": 2.094395160675049 + } + }, + "@static(1803669141)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "y": -50.0, + "z": -50.0 + }, + "rotation": { + "x": 4.188790321350098 + } + }, + "@static(692331943)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "y": 50.0, + "z": 50.0 + }, + "rotation": { + "y": 4.188790321350098, + "z": 4.188790321350098 + } + }, + "@static(106374177)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "y": 50.0, + "z": 50.0 + }, + "rotation": { + "x": 2.094395160675049, + "y": 4.188790321350098, + "z": 4.188790321350098 + } + }, + "composite_004": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0 + }, + "rotation": { + "y": 2.094395160675049, + "z": 2.094395160675049 + } + }, + "cave": { + "type": "3d.proxy", + "templateName": "cave" + }, + "composite_002": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "y": -50.0, + "z": 50.0 + }, + "rotation": { + "z": 4.188790321350098 + } + }, + "@static(1836463382)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "y": -50.0, + "z": 50.0 + }, + "rotation": { + "x": 4.188790321350098, + "z": 4.188790321350098 + } + }, + "composite_006": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "y": 50.0, + "z": -50.0 + }, + "rotation": { + "y": 4.188790321350098 + } + }, + "@static(306612792)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "y": -50.0, + "z": 50.0 + }, + "rotation": { + "x": 2.094395160675049, + "z": 4.188790321350098 + } + }, + "@static(1818544933)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": 50.0, + "y": 50.0, + "z": 50.0 + }, + "rotation": { + "x": 4.188790321350098, + "y": 4.188790321350098, + "z": 4.188790321350098 + } + }, + "@static(447212746)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "z": -50.0 + }, + "rotation": { + "x": 2.094395160675049, + "y": 2.094395160675049 + } + }, + "@static(2127036371)": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "y": 50.0, + "z": -50.0 + }, + "rotation": { + "x": 2.094395160675049, + "y": 4.188790321350098 + } + }, + "composite_000": { + "type": "3d.proxy", + "templateName": "volumes.composite", + "position": { + "x": -50.0, + "y": -50.0, + "z": -50.0 + } + } + } +} \ No newline at end of file