forked from kscience/visionforge
Refactor serialization
This commit is contained in:
parent
8f6c3822ff
commit
6b4bc6912f
@ -10,6 +10,7 @@ import hep.dataforge.vision.gdml.toVision
|
||||
import hep.dataforge.vision.react.objectTree
|
||||
import hep.dataforge.vision.solid.Solid
|
||||
import hep.dataforge.vision.solid.SolidGroup
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import hep.dataforge.vision.solid.three.ThreeCanvas
|
||||
import hep.dataforge.vision.solid.three.ThreeCanvasComponent
|
||||
import kotlinx.browser.window
|
||||
@ -50,12 +51,13 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
|
||||
}
|
||||
|
||||
fun loadData(name: String, data: String) {
|
||||
val visionManager = props.context.plugins.fetch(SolidManager).visionManager
|
||||
val parsedVision = when {
|
||||
name.endsWith(".gdml") || name.endsWith(".xml") -> {
|
||||
val gdml = GDML.decodeFromString(data)
|
||||
gdml.toVision()
|
||||
}
|
||||
name.endsWith(".json") -> SolidGroup.decodeFromString(data)
|
||||
name.endsWith(".json") -> visionManager.decodeFromString(data)
|
||||
else -> {
|
||||
window.alert("File extension is not recognized: $name")
|
||||
error("File extension is not recognized: $name")
|
||||
|
@ -4,6 +4,8 @@ import hep.dataforge.context.Global
|
||||
import hep.dataforge.vision.editor.VisualObjectEditorFragment
|
||||
import hep.dataforge.vision.editor.VisualObjectTreeFragment
|
||||
import hep.dataforge.vision.gdml.toVision
|
||||
import hep.dataforge.vision.VisionManager
|
||||
import hep.dataforge.vision.solid.Solid
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import hep.dataforge.vision.solid.SolidMaterial
|
||||
import hep.dataforge.vision.solid.fx.FX3DPlugin
|
||||
@ -17,6 +19,7 @@ class GDMLDemoApp : App(GDMLView::class)
|
||||
|
||||
class GDMLView : View() {
|
||||
private val fx3d = Global.plugins.fetch(FX3DPlugin)
|
||||
private val visionManager = Global.plugins.fetch(VisionManager)
|
||||
private val canvas = FXCanvas3D(fx3d)
|
||||
|
||||
private val treeFragment = VisualObjectTreeFragment().apply {
|
||||
@ -39,7 +42,7 @@ class GDMLView : View() {
|
||||
val file = chooseFile("Select a GDML/json file", filters = fileNameFilter).firstOrNull()
|
||||
if(file!= null) {
|
||||
runAsync {
|
||||
SolidManager.readFile(file)
|
||||
visionManager.readFile(file) as Solid
|
||||
} ui {
|
||||
canvas.render(it)
|
||||
}
|
||||
|
@ -8,13 +8,15 @@ import hep.dataforge.vision.gdml.toVision
|
||||
import hep.dataforge.vision.solid.SolidGroup
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import hep.dataforge.vision.solid.SolidMaterial
|
||||
import hep.dataforge.vision.Vision
|
||||
import hep.dataforge.vision.VisionManager
|
||||
import kscience.gdml.GDML
|
||||
import java.io.File
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
fun SolidManager.Companion.readFile(file: File): SolidGroup = when {
|
||||
fun VisionManager.readFile(file: File): Vision = when {
|
||||
file.extension == "gdml" || file.extension == "xml" -> {
|
||||
GDML.readFile(file.toPath()).toVision {
|
||||
// lUnit = LUnit.CM
|
||||
@ -31,23 +33,23 @@ fun SolidManager.Companion.readFile(file: File): SolidGroup = when {
|
||||
// }
|
||||
}
|
||||
}
|
||||
file.extension == "json" -> SolidGroup.decodeFromString(file.readText())
|
||||
file.extension == "json" -> decodeFromString(file.readText())
|
||||
file.name.endsWith("json.zip") -> {
|
||||
file.inputStream().use {
|
||||
val unzip = ZipInputStream(it, Charsets.UTF_8)
|
||||
val text = unzip.readBytes().decodeToString()
|
||||
SolidGroup.decodeFromString(text)
|
||||
decodeFromString(text)
|
||||
}
|
||||
}
|
||||
file.name.endsWith("json.gz") -> {
|
||||
file.inputStream().use {
|
||||
val unzip = GZIPInputStream(it)
|
||||
val text = unzip.readBytes().decodeToString()
|
||||
SolidGroup.decodeFromString(text)
|
||||
decodeFromString(text)
|
||||
}
|
||||
}
|
||||
else -> error("Unknown extension ${file.extension}")
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
fun SolidManager.Companion.readFile(fileName: String): SolidGroup = readFile(File(fileName))
|
||||
fun VisionManager.readFile(fileName: String): Vision = readFile(File(fileName))
|
@ -2,7 +2,7 @@ package hep.dataforge.vision.gdml.demo
|
||||
|
||||
import hep.dataforge.vision.gdml.readFile
|
||||
import hep.dataforge.vision.gdml.toVision
|
||||
import hep.dataforge.vision.solid.encodeToString
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import kscience.gdml.GDML
|
||||
import kscience.gdml.LUnit
|
||||
import java.io.File
|
||||
@ -17,11 +17,11 @@ fun main(args: Array<String>) {
|
||||
val gdml = GDML.readFile(Paths.get(inputFileName))
|
||||
//GDML.readFile(Paths.get("D:\\Work\\Projects\\visionforge\\visionforge-spatial-gdml\\src\\jvmTest\\resources\\gdml\\simple1.gdml"))
|
||||
|
||||
val visual = gdml.toVision {
|
||||
val vision = gdml.toVision {
|
||||
lUnit = LUnit.CM
|
||||
}
|
||||
|
||||
val json = visual.encodeToString()
|
||||
val json = SolidManager.encodeToString(vision)
|
||||
println(json)
|
||||
File(outputFileName).writeText(json)
|
||||
//File("D:\\Work\\Projects\\gdml.kt\\gdml-source\\cubes.json").writeText(json)
|
||||
|
@ -9,7 +9,7 @@ class FileSerializationTest {
|
||||
@Ignore
|
||||
fun testFileRead(){
|
||||
val text = this::class.java.getResourceAsStream("/cubes.json").readBytes().decodeToString()
|
||||
val visual = SolidGroup.decodeFromString(text)
|
||||
val visual = SolidManager.decodeFromString(text) as SolidGroup
|
||||
visual["composite_001".asName()]
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ private class MMDemoApp : Application {
|
||||
|
||||
private val connection = HttpClient {
|
||||
install(JsonFeature) {
|
||||
serializer = KotlinxSerializer(Json { serializersModule = SolidManager.serializersModule })
|
||||
serializer = KotlinxSerializer(Json { serializersModule = SolidManager.serializersModuleForSolids })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
package ru.mipt.npm.muon.monitor.server
|
||||
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import io.ktor.application.Application
|
||||
@ -32,15 +34,15 @@ import java.net.URI
|
||||
private val generator = Cos2TrackGenerator(JDKRandomGenerator(223))
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
fun Application.module() {
|
||||
fun Application.module(context: Context = Global) {
|
||||
val currentDir = File(".").absoluteFile
|
||||
environment.log.info("Current directory: $currentDir")
|
||||
|
||||
val solidManager = context.plugins.load(SolidManager)
|
||||
|
||||
install(DefaultHeaders)
|
||||
install(CallLogging)
|
||||
install(ContentNegotiation) {
|
||||
json(Json { serializersModule = SolidManager.serialModule }, ContentType.Application.Json)
|
||||
json(solidManager.visionManager.jsonFormat, ContentType.Application.Json)
|
||||
}
|
||||
install(Routing) {
|
||||
get("/event") {
|
||||
|
@ -94,6 +94,10 @@ public open class AbstractVision : Vision {
|
||||
properties = null
|
||||
}
|
||||
|
||||
override fun update(meta: Meta) {
|
||||
meta[Vision::properties.name].node?.let { configure(it) }
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public val descriptor: NodeDescriptor = NodeDescriptor {
|
||||
value(STYLE_KEY) {
|
||||
|
@ -68,13 +68,16 @@ public interface Vision : Configurable {
|
||||
config[STYLE_KEY] = value
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this vision using external meta.
|
||||
*/
|
||||
public fun update(meta: Meta)
|
||||
|
||||
public companion object {
|
||||
public const val TYPE: String = "vision"
|
||||
public val STYLE_KEY: Name = "@style".asName()
|
||||
|
||||
private val VISION_SERIALIZER = PolymorphicSerializer(Vision::class)
|
||||
|
||||
public fun serializer(): PolymorphicSerializer<Vision> = VISION_SERIALIZER
|
||||
public fun serializer(): PolymorphicSerializer<Vision> = PolymorphicSerializer(Vision::class)
|
||||
|
||||
public val VISIBLE_KEY: Name = "visible".asName()
|
||||
}
|
||||
|
@ -3,80 +3,21 @@ package hep.dataforge.vision
|
||||
import hep.dataforge.context.*
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.modules.SerializersModule
|
||||
import kotlinx.serialization.modules.polymorphic
|
||||
import kotlinx.serialization.modules.subclass
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
@DFExperimental
|
||||
public interface VisionForm<T : Vision> {
|
||||
public val type: KClass<out T>
|
||||
public val serializer: KSerializer<T>
|
||||
|
||||
public val name: Name
|
||||
get() = serializer.descriptor.serialName.toName()
|
||||
|
||||
/**
|
||||
* Apply a patch to given [Vision]
|
||||
*/
|
||||
public fun patch(obj: T, meta: Meta)
|
||||
|
||||
public companion object {
|
||||
public const val TYPE: String = "visionForm"
|
||||
}
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
public object SimpleGroupForm : VisionForm<SimpleVisionGroup> {
|
||||
override val type: KClass<out SimpleVisionGroup> = SimpleVisionGroup::class
|
||||
override val serializer: KSerializer<SimpleVisionGroup> = SimpleVisionGroup.serializer()
|
||||
|
||||
override fun patch(obj: SimpleVisionGroup, meta: Meta) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
public fun <T : Vision> VisionForm<T>.visionToMeta(
|
||||
vision: T,
|
||||
module: SerializersModule,
|
||||
descriptor: NodeDescriptor? = null,
|
||||
): Meta {
|
||||
val engine = Json(VisionManager.jsonConfiguration) { serializersModule = module }
|
||||
val json = engine.encodeToJsonElement(serializer, vision)
|
||||
return json.toMetaItem(descriptor).node!!
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
public fun <T : Vision> VisionForm<T>.buildVision(
|
||||
meta: Meta,
|
||||
module: SerializersModule,
|
||||
descriptor: NodeDescriptor? = null,
|
||||
): T {
|
||||
val engine = Json(VisionManager.jsonConfiguration) { serializersModule = module }
|
||||
val json = meta.toJson(descriptor)
|
||||
return engine.decodeFromJsonElement(serializer, json)
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
/**
|
||||
* Create a list of factories on first call and cache it
|
||||
* Combined [SerializersModule] for all registered visions
|
||||
*/
|
||||
private val forms by lazy {
|
||||
context.gather<VisionForm<*>>(VisionForm.TYPE).mapKeys { it.value.type }
|
||||
}
|
||||
|
||||
public val visionSerialModule: SerializersModule
|
||||
public val serializersModule: SerializersModule
|
||||
get() = SerializersModule {
|
||||
include(defaultSerialModule)
|
||||
context.gather<SerializersModule>(VISION_SERIAL_MODULE_TARGET).values.forEach {
|
||||
@ -84,33 +25,60 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <T : Vision> resolveVisionForm(type: KClass<out T>): VisionForm<T> =
|
||||
forms[type] as VisionForm<T>
|
||||
public val jsonFormat: Json
|
||||
get() = Json {
|
||||
prettyPrint = true
|
||||
useArrayPolymorphism = false
|
||||
encodeDefaults = false
|
||||
ignoreUnknownKeys = true
|
||||
serializersModule = this@VisionManager.serializersModule
|
||||
}
|
||||
|
||||
public fun decodeFromString(string: String): Vision = jsonFormat.decodeFromString(Vision.serializer(), string)
|
||||
public fun encodeToString(vision: Vision): String = jsonFormat.encodeToString(Vision.serializer(), vision)
|
||||
|
||||
public fun decodeFromJson(json: JsonElement): Vision = jsonFormat.decodeFromJsonElement(Vision.serializer(), json)
|
||||
public fun encodeToJsonElement(vision: Vision): JsonElement =
|
||||
jsonFormat.encodeToJsonElement(Vision.serializer(), vision)
|
||||
|
||||
//TODO remove double transformation with dedicated Meta serial format
|
||||
public fun decodeFromMeta(meta: Meta, descriptor: NodeDescriptor? = null): Vision =
|
||||
decodeFromJson(meta.toJson(descriptor))
|
||||
|
||||
public fun encodeToMeta(vision: Vision, descriptor: NodeDescriptor? = null): Meta =
|
||||
encodeToJsonElement(vision).toMetaItem(descriptor).node
|
||||
?: error("Expected node, but value found. Check your serializer!")
|
||||
|
||||
public fun updateVision(vision: Vision, meta: Meta) {
|
||||
|
||||
public inline fun <reified T : Vision> buildSpecificVision(meta: Meta): T {
|
||||
val factory = resolveVisionForm(T::class) ?: error("Could not resolve a form for ${meta["type"].string}")
|
||||
return factory.buildVision(meta, visionSerialModule)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
public fun buildVision(meta: Meta): Vision {
|
||||
val type = meta["type"].string ?: Vision.serializer().descriptor.serialName
|
||||
val form = forms.values.find { it.name.toString() == type } ?: error("Could not resolve a form for type $type")
|
||||
return form.buildVision(meta, visionSerialModule)
|
||||
}
|
||||
|
||||
public fun <T : Vision> writeVisionToMeta(vision: T): Meta {
|
||||
val form = resolveVisionForm(vision::class) ?: error("Could not resolve a form for $vision")
|
||||
val engine = Json(jsonConfiguration) { serializersModule = visionSerialModule }
|
||||
val json = engine.encodeToJsonElement(form.serializer, vision)
|
||||
return json.toMetaItem().node!!
|
||||
}
|
||||
|
||||
public fun patchVision(vision: Vision, meta: Meta) {
|
||||
val form = resolveVisionForm(vision::class) ?: error("Could not resolve a form for $vision")
|
||||
form.patch(vision, meta)
|
||||
}
|
||||
// public fun <T : Vision> VisionForm<T>.buildVision(meta: Meta, descriptor: NodeDescriptor? = null): T {
|
||||
// val json = meta.toJson(descriptor)
|
||||
// return jsonFormat.decodeFromJsonElement(serializer, json)
|
||||
// }
|
||||
//
|
||||
// @OptIn(ExperimentalSerializationApi::class)
|
||||
// public fun buildVision(meta: Meta): Vision {
|
||||
// val type = meta["type"].string ?: Vision.serializer().descriptor.serialName
|
||||
// val form = forms.values.find { it.name.toString() == type } ?: error("Could not resolve a form for type $type")
|
||||
// return form.buildVision(meta)
|
||||
// }
|
||||
//
|
||||
// public inline fun <reified T : Vision> buildSpecificVision(meta: Meta): T {
|
||||
// val factory = resolveVisionForm(T::class)
|
||||
// return factory.buildVision(meta)
|
||||
// }
|
||||
//
|
||||
// public fun <T : Vision> writeVisionToMeta(vision: T): Meta {
|
||||
// val form = resolveVisionForm(vision::class) ?: error("Could not resolve a form for $vision")
|
||||
// val json = jsonFormat.encodeToJsonElement(form.serializer, vision)
|
||||
// return json.toMetaItem().node!!
|
||||
// }
|
||||
//
|
||||
// public fun updateVision(vision: Vision, meta: Meta) {
|
||||
// resolveVisionForm(vision::class).patch(vision, meta)
|
||||
// }
|
||||
|
||||
public companion object : PluginFactory<VisionManager> {
|
||||
override val tag: PluginTag = PluginTag(name = "vision", group = PluginTag.DATAFORGE_GROUP)
|
||||
@ -120,14 +88,7 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
|
||||
|
||||
override fun invoke(meta: Meta, context: Context): VisionManager = VisionManager(meta)
|
||||
|
||||
public val jsonConfiguration: Json = Json {
|
||||
prettyPrint = true
|
||||
useArrayPolymorphism = false
|
||||
encodeDefaults = false
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
public val defaultSerialModule: SerializersModule = SerializersModule {
|
||||
private val defaultSerialModule: SerializersModule = SerializersModule {
|
||||
polymorphic(Vision::class) {
|
||||
subclass(SimpleVisionGroup.serializer())
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import hep.dataforge.names.Name
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.values.asValue
|
||||
|
||||
fun Sequence<MetaItem<*>?>.merge(): MetaItem<*>? {
|
||||
public fun Sequence<MetaItem<*>?>.merge(): MetaItem<*>? {
|
||||
return when (val first = firstOrNull { it != null }) {
|
||||
null -> null
|
||||
is MetaItem.ValueItem -> first //fast search for first entry if it is value
|
||||
@ -20,7 +20,7 @@ fun Sequence<MetaItem<*>?>.merge(): MetaItem<*>? {
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <reified E : Enum<E>> NodeDescriptor.enum(key: Name, default: E?) = value(key) {
|
||||
public inline fun <reified E : Enum<E>> NodeDescriptor.enum(key: Name, default: E?): Unit = value(key) {
|
||||
type(ValueType.STRING)
|
||||
default?.let {
|
||||
default(default)
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hep.dataforge.vision.gdml
|
||||
|
||||
import hep.dataforge.vision.solid.encodeToString
|
||||
import hep.dataforge.vision.solid.SolidManager
|
||||
import kscience.gdml.GDML
|
||||
import nl.adaptivity.xmlutil.StAXReader
|
||||
import org.junit.jupiter.api.Test
|
||||
@ -13,7 +13,7 @@ class TestConvertor {
|
||||
val xmlReader = StAXReader(stream, "UTF-8")
|
||||
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||
val vision = xml.toVision()
|
||||
println(vision.encodeToString())
|
||||
println(SolidManager.encodeToString(vision))
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -32,7 +32,7 @@ class TestConvertor {
|
||||
|
||||
val xmlReader = StAXReader(stream, "UTF-8")
|
||||
val xml = GDML.format.parse(GDML.serializer(), xmlReader)
|
||||
val visual = xml.toVision()
|
||||
println(visual.encodeToString())
|
||||
val vision = xml.toVision()
|
||||
println(SolidManager.encodeToString(vision))
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.vision.AbstractVision
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.UseSerializers
|
||||
|
||||
@Serializable
|
||||
public open class AbstractSolid: AbstractVision(), Solid {
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var position: Point3D? = null
|
||||
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var rotation: Point3D? = null
|
||||
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var scale: Point3D? = null
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.vision.AbstractVision
|
||||
import hep.dataforge.vision.Vision
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.UseSerializers
|
||||
|
||||
@Serializable
|
||||
@SerialName("solid")
|
||||
public open class BasicSolid: AbstractVision(), Solid {
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var position: Point3D? = null
|
||||
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var rotation: Point3D? = null
|
||||
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var scale: Point3D? = null
|
||||
|
||||
override fun update(meta: Meta) {
|
||||
fun Meta.toVector(default: Float = 0f) = Point3D(
|
||||
this[Solid.X_KEY].float ?: default,
|
||||
this[Solid.Y_KEY].float ?: default,
|
||||
this[Solid.Z_KEY].float ?: default
|
||||
)
|
||||
|
||||
meta[Solid.POSITION_KEY].node?.toVector()?.let { position = it }
|
||||
meta[Solid.ROTATION].node?.toVector()?.let { rotation = it }
|
||||
meta[Solid.SCALE_KEY].node?.toVector(1f)?.let { scale = it }
|
||||
super.update(meta)
|
||||
}
|
||||
}
|
@ -2,9 +2,6 @@
|
||||
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.vision.AbstractVision
|
||||
import hep.dataforge.vision.MutableVisionGroup
|
||||
import hep.dataforge.vision.VisionContainerBuilder
|
||||
import hep.dataforge.vision.set
|
||||
import hep.dataforge.vision.solid.Solid.Companion.solidEquals
|
||||
@ -18,7 +15,7 @@ public class Box(
|
||||
public val xSize: Float,
|
||||
public val ySize: Float,
|
||||
public val zSize: Float
|
||||
) : AbstractSolid(), GeometrySolid {
|
||||
) : BasicSolid(), GeometrySolid {
|
||||
|
||||
//TODO add helper for color configuration
|
||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.meta.update
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.vision.*
|
||||
@ -22,7 +21,7 @@ public class Composite(
|
||||
public val compositeType: CompositeType,
|
||||
public val first: Solid,
|
||||
public val second: Solid
|
||||
) : AbstractSolid(), Solid, VisionGroup {
|
||||
) : BasicSolid(), Solid, VisionGroup {
|
||||
|
||||
init {
|
||||
first.parent = this
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.vision.AbstractVision
|
||||
import hep.dataforge.vision.MutableVisionGroup
|
||||
import hep.dataforge.vision.VisionContainerBuilder
|
||||
import hep.dataforge.vision.set
|
||||
import kotlinx.serialization.SerialName
|
||||
@ -24,7 +21,7 @@ public class ConeSegment(
|
||||
public var upperRadius: Float,
|
||||
public var startAngle: Float = 0f,
|
||||
public var angle: Float = PI2
|
||||
) : AbstractSolid(), GeometrySolid {
|
||||
) : BasicSolid(), GeometrySolid {
|
||||
|
||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||
val segments = detail ?: 8
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.vision.AbstractVision
|
||||
import hep.dataforge.vision.MutableVisionGroup
|
||||
import hep.dataforge.vision.VisionContainerBuilder
|
||||
import hep.dataforge.vision.set
|
||||
import kotlinx.serialization.SerialName
|
||||
@ -13,7 +10,7 @@ import kotlinx.serialization.UseSerializers
|
||||
|
||||
@Serializable
|
||||
@SerialName("solid.convex")
|
||||
public class Convex(public val points: List<Point3D>) : AbstractSolid(), Solid
|
||||
public class Convex(public val points: List<Point3D>) : BasicSolid(), Solid
|
||||
|
||||
public inline fun VisionContainerBuilder<Solid>.convex(name: String = "", action: ConvexBuilder.() -> Unit = {}): Convex =
|
||||
ConvexBuilder().apply(action).build().also { set(name, it) }
|
||||
|
@ -1,9 +1,6 @@
|
||||
@file:UseSerializers(Point2DSerializer::class, Point3DSerializer::class)
|
||||
package hep.dataforge.vision.solid
|
||||
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.vision.AbstractVision
|
||||
import hep.dataforge.vision.MutableVisionGroup
|
||||
import hep.dataforge.vision.VisionContainerBuilder
|
||||
import hep.dataforge.vision.set
|
||||
import kotlinx.serialization.SerialName
|
||||
@ -44,7 +41,7 @@ public data class Layer(var x: Float, var y: Float, var z: Float, var scale: Flo
|
||||
public class Extruded(
|
||||
public var shape: List<Point2D> = ArrayList(),
|
||||
public var layers: MutableList<Layer> = ArrayList()
|
||||
) : AbstractSolid(), GeometrySolid {
|
||||
) : BasicSolid(), GeometrySolid {
|
||||
|
||||
public fun shape(block: Shape2DBuilder.() -> Unit) {
|
||||
this.shape = Shape2DBuilder().apply(block).build()
|
||||
|
@ -14,7 +14,7 @@ import kotlinx.serialization.UseSerializers
|
||||
|
||||
@Serializable
|
||||
@SerialName("solid.line")
|
||||
public class PolyLine(public var points: List<Point3D>) : AbstractSolid(), Solid {
|
||||
public class PolyLine(public var points: List<Point3D>) : BasicSolid(), Solid {
|
||||
|
||||
//var lineType by string()
|
||||
public var thickness: Number by number(1.0, key = SolidMaterial.MATERIAL_KEY + THICKNESS_KEY)
|
||||
|
@ -9,7 +9,7 @@ import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlin.collections.set
|
||||
|
||||
public abstract class AbstractProxy : AbstractSolid(), VisionGroup {
|
||||
public abstract class AbstractProxy : BasicSolid(), VisionGroup {
|
||||
public abstract val prototype: Vision
|
||||
|
||||
override fun getProperty(name: Name, inherit: Boolean): MetaItem<*>? {
|
||||
|
@ -8,7 +8,9 @@ import hep.dataforge.names.asName
|
||||
import hep.dataforge.vision.*
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Serializer
|
||||
import kotlinx.serialization.UseSerializers
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlin.collections.set
|
||||
|
||||
public interface PrototypeHolder {
|
||||
@ -45,8 +47,13 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
|
||||
//FIXME to be lifted to AbstractVisualGroup after https://github.com/Kotlin/kotlinx.serialization/issues/378 is fixed
|
||||
override var properties: Config? = null
|
||||
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var position: Point3D? = null
|
||||
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var rotation: Point3D? = null
|
||||
|
||||
@Serializable(Point3DSerializer::class)
|
||||
override var scale: Point3D? = null
|
||||
|
||||
@SerialName("children")
|
||||
@ -77,10 +84,6 @@ public class SolidGroup : AbstractVisionGroup(), Solid, PrototypeHolder {
|
||||
|
||||
public companion object {
|
||||
// val PROTOTYPES_KEY = NameToken("@prototypes")
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
public fun decodeFromString(json: String): SolidGroup =
|
||||
SolidManager.jsonForSolids.decodeFromString(serializer(), json).also { it.attachChildren() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ public class SolidLabel(
|
||||
public var text: String,
|
||||
public var fontSize: Double,
|
||||
public var fontFamily: String,
|
||||
) : AbstractSolid(), Solid
|
||||
) : BasicSolid(), Solid
|
||||
|
||||
public fun VisionContainerBuilder<Solid>.label(
|
||||
text: String,
|
||||
|
@ -9,73 +9,48 @@ import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.vision.SimpleVisionGroup
|
||||
import hep.dataforge.vision.Vision
|
||||
import hep.dataforge.vision.VisionForm
|
||||
import hep.dataforge.vision.VisionGroup
|
||||
import hep.dataforge.vision.VisionManager
|
||||
import hep.dataforge.vision.VisionManager.Companion.VISION_SERIAL_MODULE_TARGET
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.modules.*
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@DFExperimental
|
||||
private class SolidForm<T : Solid>(
|
||||
override val type: KClass<T>,
|
||||
override val serializer: KSerializer<T>,
|
||||
) : VisionForm<T> {
|
||||
|
||||
private fun Solid.update(meta: Meta) {
|
||||
fun Meta.toVector(default: Float = 0f) = Point3D(
|
||||
this[Solid.X_KEY].float ?: default,
|
||||
this[Solid.Y_KEY].float ?: default,
|
||||
this[Solid.Z_KEY].float ?: default
|
||||
)
|
||||
|
||||
meta[Solid.POSITION_KEY].node?.toVector()?.let { position = it }
|
||||
meta[Solid.ROTATION].node?.toVector()?.let { rotation = it }
|
||||
meta[Solid.SCALE_KEY].node?.toVector(1f)?.let { scale = it }
|
||||
meta["properties"].node?.let { configure(it) }
|
||||
}
|
||||
|
||||
override fun patch(obj: T, meta: Meta) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@DFExperimental
|
||||
private fun SerializersModule.extractFactories(): List<SolidForm<*>> {
|
||||
val list = ArrayList<SolidForm<*>>()
|
||||
|
||||
val collector = object : SerializersModuleCollector {
|
||||
override fun <T : Any> contextual(kClass: KClass<T>, serializer: KSerializer<T>) {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
override fun <Base : Any, Sub : Base> polymorphic(
|
||||
baseClass: KClass<Base>,
|
||||
actualClass: KClass<Sub>,
|
||||
actualSerializer: KSerializer<Sub>,
|
||||
) {
|
||||
if (baseClass == Vision::class) {
|
||||
@Suppress("UNCHECKED_CAST") val factory = SolidForm<Solid>(
|
||||
actualClass as KClass<Solid>,
|
||||
actualSerializer as KSerializer<Solid>
|
||||
)
|
||||
list.add(factory)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <Base : Any> polymorphicDefault(
|
||||
baseClass: KClass<Base>,
|
||||
defaultSerializerProvider: (className: String?) -> DeserializationStrategy<out Base>?,
|
||||
) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
||||
dumpTo(collector)
|
||||
return list
|
||||
}
|
||||
//@OptIn(ExperimentalSerializationApi::class)
|
||||
//@DFExperimental
|
||||
//private fun SerializersModule.extractFactories(): List<SolidForm<*>> {
|
||||
// val list = ArrayList<SolidForm<*>>()
|
||||
//
|
||||
// val collector = object : SerializersModuleCollector {
|
||||
// override fun <T : Any> contextual(kClass: KClass<T>, serializer: KSerializer<T>) {
|
||||
// //Do nothing
|
||||
// }
|
||||
//
|
||||
// override fun <Base : Any, Sub : Base> polymorphic(
|
||||
// baseClass: KClass<Base>,
|
||||
// actualClass: KClass<Sub>,
|
||||
// actualSerializer: KSerializer<Sub>,
|
||||
// ) {
|
||||
// if (baseClass == Vision::class) {
|
||||
// @Suppress("UNCHECKED_CAST") val factory: SolidForm<Solid> = SolidForm(
|
||||
// actualClass as KClass<Solid>,
|
||||
// actualSerializer as KSerializer<Solid>
|
||||
// )
|
||||
// list.add(factory)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun <Base : Any> polymorphicDefault(
|
||||
// baseClass: KClass<Base>,
|
||||
// defaultSerializerProvider: (className: String?) -> DeserializationStrategy<out Base>?,
|
||||
// ) {
|
||||
// TODO("Not yet implemented")
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// dumpTo(collector)
|
||||
// return list
|
||||
//}
|
||||
|
||||
@DFExperimental
|
||||
public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
|
||||
@ -85,8 +60,7 @@ public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
|
||||
override val tag: PluginTag get() = Companion.tag
|
||||
|
||||
override fun content(target: String): Map<Name, Any> = when (target) {
|
||||
VisionForm.TYPE -> serializersModule.extractFactories().associateBy { it.name }
|
||||
VISION_SERIAL_MODULE_TARGET -> mapOf(tag.name.toName() to serializersModule)
|
||||
VISION_SERIAL_MODULE_TARGET -> mapOf(tag.name.toName() to serializersModuleForSolids)
|
||||
else -> super.content(target)
|
||||
}
|
||||
|
||||
@ -95,44 +69,49 @@ public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
|
||||
override val type: KClass<out SolidManager> = SolidManager::class
|
||||
override fun invoke(meta: Meta, context: Context): SolidManager = SolidManager(meta)
|
||||
|
||||
public val serializersModule: SerializersModule = SerializersModule {
|
||||
private fun PolymorphicModuleBuilder<Solid>.solids() {
|
||||
subclass(SolidGroup.serializer())
|
||||
subclass(Proxy.serializer())
|
||||
subclass(Composite.serializer())
|
||||
subclass(Tube.serializer())
|
||||
subclass(Box.serializer())
|
||||
subclass(Convex.serializer())
|
||||
subclass(Extruded.serializer())
|
||||
subclass(PolyLine.serializer())
|
||||
subclass(SolidLabel.serializer())
|
||||
subclass(Sphere.serializer())
|
||||
}
|
||||
|
||||
public val serializersModuleForSolids: SerializersModule = SerializersModule {
|
||||
contextual(Point3DSerializer)
|
||||
contextual(Point2DSerializer)
|
||||
|
||||
polymorphic(Vision::class) {
|
||||
subclass(SimpleVisionGroup.serializer())
|
||||
subclass(SolidGroup.serializer())
|
||||
subclass(Proxy.serializer())
|
||||
subclass(Composite.serializer())
|
||||
subclass(Tube.serializer())
|
||||
subclass(Box.serializer())
|
||||
subclass(Convex.serializer())
|
||||
subclass(Extruded.serializer())
|
||||
subclass(PolyLine.serializer())
|
||||
subclass(SolidLabel.serializer())
|
||||
subclass(Sphere.serializer())
|
||||
solids()
|
||||
}
|
||||
|
||||
polymorphic(Solid::class) {
|
||||
subclass(SolidGroup.serializer())
|
||||
subclass(Proxy.serializer())
|
||||
subclass(Composite.serializer())
|
||||
subclass(Tube.serializer())
|
||||
subclass(Box.serializer())
|
||||
subclass(Convex.serializer())
|
||||
subclass(Extruded.serializer())
|
||||
subclass(PolyLine.serializer())
|
||||
subclass(SolidLabel.serializer())
|
||||
subclass(Sphere.serializer())
|
||||
solids()
|
||||
}
|
||||
}
|
||||
|
||||
val jsonForSolids = Json {
|
||||
public val jsonForSolids = Json{
|
||||
prettyPrint = true
|
||||
useArrayPolymorphism = false
|
||||
encodeDefaults = false
|
||||
ignoreUnknownKeys = true
|
||||
serializersModule = this@Companion.serializersModule
|
||||
serializersModule = SolidManager.serializersModuleForSolids
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
public fun encodeToString(solid: Solid): String = jsonForSolids.encodeToString(Vision.serializer(), solid)
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
public fun decodeFromString(str: String): Vision = jsonForSolids.decodeFromString(Vision.serializer(), str).also {
|
||||
if(it is VisionGroup){
|
||||
it.attachChildren()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class Sphere(
|
||||
public var phi: Float = PI2,
|
||||
public var thetaStart: Float = 0f,
|
||||
public var theta: Float = PI.toFloat(),
|
||||
) : AbstractSolid(), GeometrySolid {
|
||||
) : BasicSolid(), GeometrySolid {
|
||||
|
||||
override fun <T : Any> toGeometry(geometryBuilder: GeometryBuilder<T>) {
|
||||
fun point3DfromSphCoord(r: Float, theta: Float, phi: Float): Point3D {
|
||||
|
@ -19,7 +19,7 @@ public class Tube(
|
||||
public var innerRadius: Float = 0f,
|
||||
public var startAngle: Float = 0f,
|
||||
public var angle: Float = PI2,
|
||||
) : AbstractSolid(), GeometrySolid {
|
||||
) : BasicSolid(), GeometrySolid {
|
||||
|
||||
init {
|
||||
require(radius > 0)
|
||||
|
@ -105,14 +105,4 @@ internal object PrototypesSerializer : KSerializer<MutableVisionGroup> {
|
||||
override fun serialize(encoder: Encoder, value: MutableVisionGroup) {
|
||||
mapSerializer.serialize(encoder, value.children)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
public fun Vision.encodeToString(): String = SolidManager.jsonForSolids.encodeToString(Vision.serializer(), this)
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
public fun Vision.Companion.decodeFromString(str: String): Vision = SolidManager.jsonForSolids.decodeFromString(serializer(), str).also {
|
||||
if(it is VisionGroup){
|
||||
it.attachChildren()
|
||||
}
|
||||
}
|
@ -8,6 +8,7 @@ import hep.dataforge.vision.get
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
/**
|
||||
* Create and attach new proxied group
|
||||
*/
|
||||
@ -29,9 +30,9 @@ class SerializationTest {
|
||||
x = 100
|
||||
z = -100
|
||||
}
|
||||
val string = cube.encodeToString()
|
||||
val string = SolidManager.encodeToString(cube)
|
||||
println(string)
|
||||
val newCube = Vision.decodeFromString(string)
|
||||
val newCube = SolidManager.decodeFromString(string)
|
||||
assertEquals(cube.config, newCube.config)
|
||||
}
|
||||
|
||||
@ -50,9 +51,9 @@ class SerializationTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
val string = group.encodeToString()
|
||||
val string = SolidManager.encodeToString(group)
|
||||
println(string)
|
||||
val reconstructed = SolidGroup.decodeFromString(string)
|
||||
val reconstructed = SolidManager.decodeFromString(string) as SolidGroup
|
||||
assertEquals(group["cube"]?.config, reconstructed["cube"]?.config)
|
||||
}
|
||||
|
||||
|
@ -18,10 +18,10 @@ class SolidPluginTest {
|
||||
@DFExperimental
|
||||
@Test
|
||||
fun testPluginConverter(){
|
||||
val plugin = Global.plugins.fetch(SolidManager).visionManager
|
||||
val meta = plugin.writeVisionToMeta(vision)
|
||||
val visionManager = Global.plugins.fetch(SolidManager).visionManager
|
||||
val meta = visionManager.encodeToMeta(vision)
|
||||
|
||||
val reconstructed = plugin.buildSpecificVision<SolidGroup>(meta)
|
||||
val reconstructed = visionManager.decodeFromMeta(meta) as SolidGroup
|
||||
|
||||
assertEquals(vision["aBox"],reconstructed["aBox"])
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hep.dataforge.vision.solid.three
|
||||
|
||||
import hep.dataforge.vision.solid.AbstractSolid
|
||||
import hep.dataforge.vision.solid.BasicSolid
|
||||
import hep.dataforge.vision.solid.Solid
|
||||
import info.laht.threekt.core.Object3D
|
||||
import kotlinx.serialization.Serializable
|
||||
@ -13,6 +13,6 @@ public interface ThreeVision : Solid {
|
||||
}
|
||||
|
||||
@Serializable
|
||||
public class CustomThreeVision(public val threeFactory: ThreeFactory<Solid>) : AbstractSolid(), ThreeVision {
|
||||
public class CustomThreeVision(public val threeFactory: ThreeFactory<Solid>) : BasicSolid(), ThreeVision {
|
||||
override fun toObject3D(): Object3D = threeFactory(this)
|
||||
}
|
Loading…
Reference in New Issue
Block a user