feature/root #69
@ -1,22 +0,0 @@
|
|||||||
package ru.mipt.npm.root
|
|
||||||
|
|
||||||
import kotlinx.serialization.Contextual
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
@SerialName("TGeoManager")
|
|
||||||
public class TGeoManager : TNamed() {
|
|
||||||
|
|
||||||
@Contextual
|
|
||||||
public val fMatrices: TObjArray<@Contextual TGeoMatrix> = TObjArray.getEmpty()
|
|
||||||
|
|
||||||
@Contextual
|
|
||||||
public val fShapes: TObjArray<@Contextual TGeoShape> = TObjArray.getEmpty()
|
|
||||||
|
|
||||||
@Contextual
|
|
||||||
public val fVolumes: TObjArray<@Contextual TGeoVolume> = TObjArray.getEmpty()
|
|
||||||
|
|
||||||
@Contextual
|
|
||||||
public val fNodes: TObjArray<@Contextual TGeoNode> = TObjArray.getEmpty()
|
|
||||||
}
|
|
@ -0,0 +1,140 @@
|
|||||||
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import space.kscience.dataforge.meta.*
|
||||||
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.dataforge.names.asName
|
||||||
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
|
||||||
|
public typealias RefCache = List<Meta>
|
||||||
|
|
||||||
|
public interface ObjectRef<T : TObjectScheme> {
|
||||||
|
public fun resolve(refCache: RefCache): T?
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ChildObjectRef<T : TObjectScheme>(
|
||||||
|
val spec: Specification<T>,
|
||||||
|
val metaProvider: () -> Meta?
|
||||||
|
) : ObjectRef<T> {
|
||||||
|
override fun resolve(refCache: RefCache): T? {
|
||||||
|
val meta = metaProvider() ?: return null
|
||||||
|
meta["\$ref"]?.int?.let { refId ->
|
||||||
|
return spec.read(refCache[refId])
|
||||||
|
}
|
||||||
|
return spec.read(meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T: TObjectScheme> List<ObjectRef<T>>.resolve(refCache: RefCache): List<T> = map { it.resolve(refCache)!! }
|
||||||
|
|
||||||
|
|
||||||
|
public open class TObjectScheme : Scheme() {
|
||||||
|
|
||||||
|
public val typename: String by string(key = "_typename".asName()) { error("Type is not defined") }
|
||||||
|
|
||||||
|
internal fun <T : TObjectScheme> tObjectArray(
|
||||||
|
spec: Specification<T>
|
||||||
|
): ReadOnlyProperty<Any?, List<ObjectRef<T>>> = ReadOnlyProperty { _, property ->
|
||||||
|
meta.getIndexed(Name.of(property.name, "arr")).values.map { ChildObjectRef(spec){it} }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun <T : TObjectScheme> refSpec(
|
||||||
|
spec: Specification<T>,
|
||||||
|
key: Name? = null
|
||||||
|
): ReadOnlyProperty<Any?, ObjectRef<T>> = ReadOnlyProperty { _, property ->
|
||||||
|
ChildObjectRef(spec) { meta[key ?: property.name.asName()] }
|
||||||
|
}
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TObjectScheme>(::TObjectScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class TNamedScheme : TObjectScheme() {
|
||||||
|
public val fName: String by string("")
|
||||||
|
public val fTitle: String by string("")
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TNamedScheme>(::TNamedScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TGeoMaterialScheme : TNamedScheme() {
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TGeoMaterialScheme>(::TGeoMaterialScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TGeoMediumScheme : TNamedScheme() {
|
||||||
|
public val fMaterial: ObjectRef<TGeoMaterialScheme> by refSpec(TGeoMaterialScheme)
|
||||||
|
public val fParams: DoubleArray by doubleArray()
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TGeoMediumScheme>(::TGeoMediumScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TGeoShapeScheme : TNamedScheme() {
|
||||||
|
public val fDX: Double by double(0.0)
|
||||||
|
public val fDY: Double by double(0.0)
|
||||||
|
public val fDZ: Double by double(0.0)
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TGeoShapeScheme>(::TGeoShapeScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TGeoVolumeScheme : TNamedScheme() {
|
||||||
|
public val fNodes: List<ObjectRef<TGeoNodeScheme>> by tObjectArray(TGeoNodeScheme)
|
||||||
|
public val fShape: ObjectRef<TGeoShapeScheme> by refSpec(TGeoShapeScheme)
|
||||||
|
public val fMedium: ObjectRef<TGeoMediumScheme> by refSpec(TGeoMediumScheme)
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TGeoVolumeScheme>(::TGeoVolumeScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TGeoNodeScheme : TNamedScheme() {
|
||||||
|
public val fVolume: ObjectRef<TGeoVolumeScheme> by refSpec(TGeoVolumeScheme)
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TGeoNodeScheme>(::TGeoNodeScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TGeoMatrixScheme : TNamedScheme() {
|
||||||
|
public companion object : SchemeSpec<TGeoMatrixScheme>(::TGeoMatrixScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class TGeoBoolNodeScheme : TObjectScheme() {
|
||||||
|
public val fLeft: ObjectRef<TGeoShapeScheme> by refSpec(TGeoShapeScheme)
|
||||||
|
public val fLeftMat: ObjectRef<TGeoMatrixScheme> by refSpec(TGeoMatrixScheme)
|
||||||
|
|
||||||
|
public val fRight: ObjectRef<TGeoShapeScheme> by refSpec(TGeoShapeScheme)
|
||||||
|
public val fRightMat: ObjectRef<TGeoMatrixScheme> by refSpec(TGeoMatrixScheme)
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TGeoBoolNodeScheme>(::TGeoBoolNodeScheme)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class TGeoManagerScheme : TNamedScheme() {
|
||||||
|
public val fMatrices: List<ObjectRef<TGeoMatrixScheme>> by tObjectArray(TGeoMatrixScheme)
|
||||||
|
|
||||||
|
public val fShapes: List<ObjectRef<TGeoShapeScheme>> by tObjectArray(TGeoShapeScheme)
|
||||||
|
|
||||||
|
public val fVolumes: List<ObjectRef<TGeoVolumeScheme>> by tObjectArray(TGeoVolumeScheme)
|
||||||
|
|
||||||
|
public val fNodes: List<ObjectRef<TGeoNodeScheme>> by tObjectArray(TGeoNodeScheme)
|
||||||
|
|
||||||
|
public val refCache: List<Meta> by lazy {
|
||||||
|
val res = ArrayList<Meta>(4096)
|
||||||
|
fun fillCache(element: Meta) {
|
||||||
|
if(element["\$ref"] == null) {
|
||||||
|
res.add(element)
|
||||||
|
element.items.values.forEach {
|
||||||
|
if (!it.isLeaf) {
|
||||||
|
fillCache(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fillCache(meta)
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
public companion object : SchemeSpec<TGeoManagerScheme>(::TGeoManagerScheme) {
|
||||||
|
|
||||||
|
public fun parse(string: String): TGeoManagerScheme {
|
||||||
|
val meta = Json.decodeFromString(MetaSerializer, string)
|
||||||
|
return read(meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,261 +0,0 @@
|
|||||||
package ru.mipt.npm.root
|
|
||||||
|
|
||||||
import kotlinx.serialization.DeserializationStrategy
|
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
|
||||||
import kotlinx.serialization.KSerializer
|
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
|
||||||
import kotlinx.serialization.encoding.Decoder
|
|
||||||
import kotlinx.serialization.json.*
|
|
||||||
import kotlinx.serialization.modules.*
|
|
||||||
|
|
||||||
|
|
||||||
private fun <T> jsonRootDeserializer(tSerializer: KSerializer<T>, builder: (JsonElement) -> T): DeserializationStrategy<T> = object :
|
|
||||||
DeserializationStrategy<T> {
|
|
||||||
private val jsonElementSerializer = JsonElement.serializer()
|
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor
|
|
||||||
get() = jsonElementSerializer.descriptor
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): T {
|
|
||||||
val json = decoder.decodeSerializableValue(jsonElementSerializer)
|
|
||||||
return builder(json)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load Json encoded TObject
|
|
||||||
*/
|
|
||||||
public fun <T: TObject> TObject.Companion.decodeFromJson(serializer: KSerializer<T>, jsonElement: JsonElement): T =
|
|
||||||
RootDecoder.decode(serializer, jsonElement)
|
|
||||||
|
|
||||||
public fun <T: TObject> TObject.Companion.decodeFromString(serializer: KSerializer<T>, string: String): T {
|
|
||||||
val json = RootDecoder.json.parseToJsonElement(string)
|
|
||||||
return RootDecoder.decode(serializer, json)
|
|
||||||
}
|
|
||||||
|
|
||||||
private object RootDecoder {
|
|
||||||
|
|
||||||
private class RootUnrefSerializer<T>(
|
|
||||||
private val tSerializer: KSerializer<T>,
|
|
||||||
private val refCache: List<RefEntry>,
|
|
||||||
) : KSerializer<T> by tSerializer {
|
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): T {
|
|
||||||
val input = decoder as JsonDecoder
|
|
||||||
val element = input.decodeJsonElement()
|
|
||||||
val refId = (element as? JsonObject)?.get("\$ref")?.jsonPrimitive?.int
|
|
||||||
val ref = if (refId != null) {
|
|
||||||
//println("Substituting ${tSerializer.descriptor.serialName} ref $refId")
|
|
||||||
//Forward ref for shapes
|
|
||||||
when (tSerializer.descriptor.serialName) {
|
|
||||||
"TGeoShape" -> return TGeoShapeRef {
|
|
||||||
refCache[refId].getOrPutValue {
|
|
||||||
input.json.decodeFromJsonElement(tSerializer, it) as TGeoShape
|
|
||||||
}
|
|
||||||
} as T
|
|
||||||
"TGeoVolumeAssembly" -> return TGeoVolumeAssemblyRef {
|
|
||||||
refCache[refId].getOrPutValue {
|
|
||||||
input.json.decodeFromJsonElement(tSerializer, it) as TGeoVolumeAssembly
|
|
||||||
}
|
|
||||||
} as T
|
|
||||||
//Do unref
|
|
||||||
else -> refCache[refId]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
refCache.find { it.element == element } ?: error("Element '$element' not found in the cache")
|
|
||||||
}
|
|
||||||
|
|
||||||
return ref.getOrPutValue {
|
|
||||||
// val actualTypeName = it.jsonObject["_typename"]?.jsonPrimitive?.content
|
|
||||||
input.json.decodeFromJsonElement(tSerializer, it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> KSerializer<T>.unref(refCache: List<RefEntry>): KSerializer<T> =
|
|
||||||
RootUnrefSerializer(this, refCache)
|
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
|
||||||
fun unrefSerializersModule(
|
|
||||||
refCache: List<RefEntry>
|
|
||||||
): SerializersModule = SerializersModule {
|
|
||||||
include(serializersModule)
|
|
||||||
|
|
||||||
//contextual(TGeoManager.serializer().unref(refCache))
|
|
||||||
contextual(TObjArray::class) { TObjArray.serializer(it[0]).unref(refCache) }
|
|
||||||
//contextual(TGeoVolumeAssembly.serializer().unref(refCache))
|
|
||||||
//contextual(TGeoShapeAssembly.serializer().unref(refCache))
|
|
||||||
contextual(TGeoRotation.serializer().unref(refCache))
|
|
||||||
contextual(TGeoMedium.serializer().unref(refCache))
|
|
||||||
//contextual(TGeoVolume.serializer().unref(refCache))
|
|
||||||
//contextual(TGeoMatrix.serializer().unref(refCache))
|
|
||||||
//contextual(TGeoNode.serializer().unref(refCache))
|
|
||||||
//contextual(TGeoNodeOffset.serializer().unref(refCache))
|
|
||||||
//contextual(TGeoNodeMatrix.serializer().unref(refCache))
|
|
||||||
//contextual(TGeoShape.serializer().unref(refCache))
|
|
||||||
//contextual(TObject.serializer().unref(refCache))
|
|
||||||
|
|
||||||
|
|
||||||
polymorphicDefault(TGeoShape::class) {
|
|
||||||
if (it == null) {
|
|
||||||
TGeoShape.serializer().unref(refCache)
|
|
||||||
} else {
|
|
||||||
error("Unrecognized shape $it")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphicDefault(TGeoMatrix::class) {
|
|
||||||
if (it == null) {
|
|
||||||
TGeoMatrix.serializer().unref(refCache)
|
|
||||||
} else {
|
|
||||||
error("Unrecognized matrix $it")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphicDefault(TGeoVolume::class) {
|
|
||||||
if (it == null) {
|
|
||||||
TGeoVolume.serializer().unref(refCache)
|
|
||||||
} else {
|
|
||||||
error("Unrecognized volume $it")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphicDefault(TGeoNode::class) {
|
|
||||||
if (it == null) {
|
|
||||||
TGeoNode.serializer().unref(refCache)
|
|
||||||
} else {
|
|
||||||
error("Unrecognized node $it")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of Json with unfolding Root references. This instance could not be reused because of the cache.
|
|
||||||
*/
|
|
||||||
private fun unrefJson(refCache: MutableList<RefEntry>): Json = Json {
|
|
||||||
encodeDefaults = true
|
|
||||||
ignoreUnknownKeys = true
|
|
||||||
classDiscriminator = "_typename"
|
|
||||||
serializersModule = unrefSerializersModule(refCache)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun <T: TObject> decode(sourceDeserializer: KSerializer<T>, source: JsonElement): T {
|
|
||||||
val refCache = ArrayList<RefEntry>()
|
|
||||||
|
|
||||||
fun fillCache(element: JsonElement) {
|
|
||||||
when (element) {
|
|
||||||
is JsonObject -> {
|
|
||||||
if (element["_typename"] != null) {
|
|
||||||
refCache.add(RefEntry(element))
|
|
||||||
}
|
|
||||||
element.values.forEach {
|
|
||||||
fillCache(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is JsonArray -> {
|
|
||||||
element.forEach {
|
|
||||||
fillCache(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
//ignore primitives
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fillCache(source)
|
|
||||||
|
|
||||||
return unrefJson(refCache).decodeFromJsonElement(sourceDeserializer.unref(refCache), source)
|
|
||||||
}
|
|
||||||
|
|
||||||
class RefEntry(val element: JsonElement) {
|
|
||||||
|
|
||||||
var value: Any? = null
|
|
||||||
|
|
||||||
fun <T> getOrPutValue(builder: (JsonElement) -> T): T {
|
|
||||||
if (value == null) {
|
|
||||||
value = builder(element)
|
|
||||||
}
|
|
||||||
return value as T
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String = element.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun PolymorphicModuleBuilder<TGeoShape>.shapes() {
|
|
||||||
subclass(TGeoBBox.serializer())
|
|
||||||
subclass(TGeoCompositeShape.serializer())
|
|
||||||
subclass(TGeoXtru.serializer())
|
|
||||||
subclass(TGeoTube.serializer())
|
|
||||||
subclass(TGeoTubeSeg.serializer())
|
|
||||||
subclass(TGeoPcon.serializer())
|
|
||||||
subclass(TGeoPgon.serializer())
|
|
||||||
subclass(TGeoShapeAssembly.serializer())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun PolymorphicModuleBuilder<TGeoMatrix>.matrices() {
|
|
||||||
subclass(TGeoIdentity.serializer())
|
|
||||||
subclass(TGeoHMatrix.serializer())
|
|
||||||
subclass(TGeoTranslation.serializer())
|
|
||||||
subclass(TGeoRotation.serializer())
|
|
||||||
subclass(TGeoCombiTrans.serializer())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun PolymorphicModuleBuilder<TGeoBoolNode>.boolNodes() {
|
|
||||||
subclass(TGeoIntersection.serializer())
|
|
||||||
subclass(TGeoUnion.serializer())
|
|
||||||
subclass(TGeoSubtraction.serializer())
|
|
||||||
}
|
|
||||||
|
|
||||||
private val serializersModule = SerializersModule {
|
|
||||||
|
|
||||||
// polymorphic(TObject::class) {
|
|
||||||
// default { JsonRootSerializer }
|
|
||||||
//
|
|
||||||
// shapes()
|
|
||||||
// matrices()
|
|
||||||
// boolNodes()
|
|
||||||
//
|
|
||||||
// subclass(TGeoMaterial.serializer())
|
|
||||||
// subclass(TGeoMixture.serializer())
|
|
||||||
//
|
|
||||||
// subclass(TGeoMedium.serializer())
|
|
||||||
//
|
|
||||||
// //subclass(TGeoNode.serializer())
|
|
||||||
// subclass(TGeoNodeMatrix.serializer())
|
|
||||||
// subclass(TGeoVolume.serializer())
|
|
||||||
// subclass(TGeoVolumeAssembly.serializer())
|
|
||||||
// subclass(TGeoManager.serializer())
|
|
||||||
// }
|
|
||||||
|
|
||||||
polymorphic(TGeoShape::class) {
|
|
||||||
shapes()
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphic(TGeoMatrix::class) {
|
|
||||||
matrices()
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphic(TGeoBoolNode::class) {
|
|
||||||
boolNodes()
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphic(TGeoNode::class) {
|
|
||||||
subclass(TGeoNodeMatrix.serializer())
|
|
||||||
subclass(TGeoNodeOffset.serializer())
|
|
||||||
}
|
|
||||||
|
|
||||||
polymorphic(TGeoVolume::class) {
|
|
||||||
subclass(TGeoVolume.serializer())
|
|
||||||
subclass(TGeoVolumeAssembly.serializer())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val json = Json {
|
|
||||||
encodeDefaults = true
|
|
||||||
ignoreUnknownKeys = true
|
|
||||||
classDiscriminator = "_typename"
|
|
||||||
serializersModule = this@RootDecoder.serializersModule
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,217 @@
|
|||||||
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
|
import space.kscience.dataforge.meta.*
|
||||||
|
import space.kscience.dataforge.names.Name
|
||||||
|
import space.kscience.dataforge.names.asName
|
||||||
|
import space.kscience.dataforge.names.plus
|
||||||
|
import space.kscience.visionforge.solid.*
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.math.atan2
|
||||||
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
private val solidsName = "solids".asName()
|
||||||
|
private val volumesName = "volumes".asName()
|
||||||
|
|
||||||
|
private operator fun Number.times(d: Double) = toDouble() * d
|
||||||
|
|
||||||
|
private operator fun Number.times(f: Float) = toFloat() * f
|
||||||
|
|
||||||
|
private fun degToRad(d: Double) = d * PI / 180.0
|
||||||
|
|
||||||
|
// converting to XYZ to Tait–Bryan angles according to https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
|
||||||
|
private fun Solid.rotate(rot: DoubleArray) {
|
||||||
|
val xAngle = atan2(-rot[5], rot[8])
|
||||||
|
val yAngle = atan2(rot[2], sqrt(1.0 - rot[2].pow(2)))
|
||||||
|
val zAngle = atan2(-rot[1], rot[0])
|
||||||
|
rotation = Point3D(xAngle, yAngle, zAngle)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Solid.translate(trans: DoubleArray) {
|
||||||
|
val (x, y, z) = trans
|
||||||
|
position = Point3D(x, y, z)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Solid.useMatrix(matrix: TGeoMatrixScheme?) {
|
||||||
|
if (matrix == null) return
|
||||||
|
when (matrix.typename) {
|
||||||
|
"TGeoIdentity" -> {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
"TGeoTranslation" -> {
|
||||||
|
val fTranslation by matrix.doubleArray()
|
||||||
|
translate(fTranslation)
|
||||||
|
}
|
||||||
|
"TGeoRotation" -> {
|
||||||
|
val fRotationMatrix by matrix.doubleArray()
|
||||||
|
rotate(fRotationMatrix)
|
||||||
|
}
|
||||||
|
"TGeoCombiTrans" -> {
|
||||||
|
val fTranslation by matrix.doubleArray()
|
||||||
|
|
||||||
|
translate(fTranslation)
|
||||||
|
if (matrix.meta["fRotationMatrix"] != null) {
|
||||||
|
val fRotationMatrix by matrix.doubleArray()
|
||||||
|
rotate(fRotationMatrix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"TGeoHMatrix" -> {
|
||||||
|
val fTranslation by matrix.doubleArray()
|
||||||
|
val fRotationMatrix by matrix.doubleArray()
|
||||||
|
val fScale by matrix.doubleArray()
|
||||||
|
translate(fTranslation)
|
||||||
|
rotate(fRotationMatrix)
|
||||||
|
scale = Point3D(fScale[0], fScale[1], fScale[2])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SolidGroup.addShape(shape: TGeoShapeScheme, refCache: RefCache) {
|
||||||
|
when (shape.typename) {
|
||||||
|
"TGeoCompositeShape" -> {
|
||||||
|
val bool by shape.spec(TGeoBoolNodeScheme)
|
||||||
|
val compositeType = when (bool.typename) {
|
||||||
|
"TGeoIntersection" -> CompositeType.INTERSECT
|
||||||
|
"TGeoSubtraction" -> CompositeType.SUBTRACT
|
||||||
|
"TGeoUnion" -> CompositeType.UNION
|
||||||
|
else -> error("Unknown bool node type ${bool.typename}")
|
||||||
|
}
|
||||||
|
composite(compositeType, name = shape.fName) {
|
||||||
|
addShape(bool.fLeft.resolve(refCache)!!, refCache).apply {
|
||||||
|
useMatrix(bool.fLeftMat.resolve(refCache))
|
||||||
|
}
|
||||||
|
addShape(bool.fRight.resolve(refCache)!!, refCache).apply {
|
||||||
|
useMatrix(bool.fRightMat.resolve(refCache))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"TGeoXtru" -> {
|
||||||
|
val fNvert by shape.meta.int(0)
|
||||||
|
val fX by shape.meta.doubleArray()
|
||||||
|
val fY by shape.meta.doubleArray()
|
||||||
|
val fNz by shape.meta.int(0)
|
||||||
|
val fZ by shape.meta.doubleArray()
|
||||||
|
val fX0 by shape.meta.doubleArray()
|
||||||
|
val fY0 by shape.meta.doubleArray()
|
||||||
|
val fScale by shape.meta.doubleArray()
|
||||||
|
|
||||||
|
extruded(name = shape.fName) {
|
||||||
|
(0 until fNvert).forEach { index ->
|
||||||
|
shape {
|
||||||
|
point(fX[index], fY[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(0 until fNz).forEach { index ->
|
||||||
|
layer(
|
||||||
|
fZ[index],
|
||||||
|
fX0[index],
|
||||||
|
fY0[index],
|
||||||
|
fScale[index]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"TGeoTube" -> {
|
||||||
|
val fRmax by shape.meta.double(0.0)
|
||||||
|
val fDz by shape.meta.double(0.0)
|
||||||
|
val fRmin by shape.meta.double(0.0)
|
||||||
|
|
||||||
|
tube(
|
||||||
|
radius = fRmax,
|
||||||
|
height = fDz * 2,
|
||||||
|
innerRadius = fRmin,
|
||||||
|
name = shape.fName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"TGeoTubeSeg" -> {
|
||||||
|
val fRmax by shape.meta.double(0.0)
|
||||||
|
val fDz by shape.meta.double(0.0)
|
||||||
|
val fRmin by shape.meta.double(0.0)
|
||||||
|
val fPhi1 by shape.meta.double(0.0)
|
||||||
|
val fPhi2 by shape.meta.double(0.0)
|
||||||
|
|
||||||
|
tube(
|
||||||
|
radius = fRmax,
|
||||||
|
height = fDz * 2,
|
||||||
|
innerRadius = fRmin,
|
||||||
|
startAngle = degToRad(fPhi1),
|
||||||
|
angle = degToRad(fPhi2 - fPhi1),
|
||||||
|
name = shape.fName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
"TGeoPcon" -> {
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
"TGeoPgon" -> {
|
||||||
|
TODO()
|
||||||
|
}
|
||||||
|
"TGeoShapeAssembly" -> {
|
||||||
|
val fVolume by shape.refSpec(TGeoVolumeScheme)
|
||||||
|
volume(fVolume.resolve(refCache)!!, refCache)
|
||||||
|
}
|
||||||
|
"TGeoBBox" -> {
|
||||||
|
box(shape.fDX * 2, shape.fDY * 2, shape.fDZ * 2, name = shape.fName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SolidGroup.node(obj: TGeoNodeScheme, refCache: RefCache) {
|
||||||
|
val volume = obj.fVolume.resolve(refCache)
|
||||||
|
if (volume != null) {
|
||||||
|
volume(volume, refCache, obj.fName).apply {
|
||||||
|
when (obj.typename) {
|
||||||
|
"TGeoNodeMatrix" -> {
|
||||||
|
val fMatrix by obj.refSpec(TGeoMatrixScheme)
|
||||||
|
useMatrix(fMatrix.resolve(refCache))
|
||||||
|
}
|
||||||
|
"TGeoNodeOffset" -> {
|
||||||
|
val fOffset by obj.meta.double(0.0)
|
||||||
|
x = fOffset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildGroup(volume: TGeoVolumeScheme, refCache: RefCache): SolidGroup = SolidGroup {
|
||||||
|
volume.fShape.resolve(refCache)?.let { addShape(it, refCache) }
|
||||||
|
volume.fNodes.let {
|
||||||
|
it.forEach { obj ->
|
||||||
|
node(obj.resolve(refCache)!!, refCache)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val SolidGroup.rootPrototypes: SolidGroup get() = (parent as? SolidGroup)?.rootPrototypes ?: this
|
||||||
|
|
||||||
|
private fun SolidGroup.volume(
|
||||||
|
volume: TGeoVolumeScheme,
|
||||||
|
refCache: RefCache,
|
||||||
|
name: String? = null,
|
||||||
|
cache: Boolean = true
|
||||||
|
): Solid {
|
||||||
|
val group = buildGroup(volume, refCache)
|
||||||
|
val combinedName = if (volume.fName.isEmpty()) {
|
||||||
|
name
|
||||||
|
} else if (name == null) {
|
||||||
|
volume.fName
|
||||||
|
} else {
|
||||||
|
"${name}_${volume.fName}"
|
||||||
|
}
|
||||||
|
return if (!cache) {
|
||||||
|
set(combinedName?.let { Name.parse(it)},group)
|
||||||
|
group
|
||||||
|
} else newRef(
|
||||||
|
name = combinedName,
|
||||||
|
obj = group,
|
||||||
|
prototypeHolder = rootPrototypes,
|
||||||
|
templateName = volumesName + Name.parse(combinedName ?: "volume[${group.hashCode()}]")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun TGeoManagerScheme.toSolid(): SolidGroup = SolidGroup {
|
||||||
|
fNodes.forEach {
|
||||||
|
node(it.resolve(refCache)!!, refCache)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("TGeoManager")
|
||||||
|
public class TGeoManager : TNamed() {
|
||||||
|
|
||||||
|
public val fMatrices: TObjArray<TGeoMatrix> = TObjArray.getEmpty()
|
||||||
|
|
||||||
|
public val fShapes: TObjArray<TGeoShape> = TObjArray.getEmpty()
|
||||||
|
|
||||||
|
public val fVolumes: TObjArray<TGeoVolume> = TObjArray.getEmpty()
|
||||||
|
|
||||||
|
public val fNodes: TObjArray<TGeoNode> = TObjArray.getEmpty()
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import kotlinx.serialization.Contextual
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import kotlinx.serialization.Contextual
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import kotlinx.serialization.Contextual
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
@ -6,7 +6,7 @@ import kotlinx.serialization.Serializable
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("TGeoNode")
|
@SerialName("TGeoNode")
|
||||||
public sealed class TGeoNode : TNamed() {
|
public open class TGeoNode : TNamed() {
|
||||||
public val fGeoAtt: UInt = 0u
|
public val fGeoAtt: UInt = 0u
|
||||||
|
|
||||||
@Contextual
|
@Contextual
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import kotlinx.serialization.Contextual
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import kotlinx.serialization.Contextual
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
@ -15,7 +15,7 @@ public open class TGeoVolume : TNamed() {
|
|||||||
public val fFillStyle: Int? = null
|
public val fFillStyle: Int? = null
|
||||||
|
|
||||||
@Contextual
|
@Contextual
|
||||||
public val fNodes: TObjArray<TGeoNode>? = null
|
public val fNodes: TObjArray<@Contextual TGeoNode>? = null
|
||||||
|
|
||||||
@Contextual
|
@Contextual
|
||||||
public val fShape: TGeoShape? = null
|
public val fShape: TGeoShape? = null
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import kotlinx.serialization.Contextual
|
import kotlinx.serialization.Contextual
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
@ -0,0 +1,235 @@
|
|||||||
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.json.*
|
||||||
|
import kotlinx.serialization.modules.SerializersModule
|
||||||
|
import kotlinx.serialization.modules.contextual
|
||||||
|
import kotlinx.serialization.modules.polymorphic
|
||||||
|
import kotlinx.serialization.modules.subclass
|
||||||
|
|
||||||
|
|
||||||
|
private fun <T> jsonRootDeserializer(
|
||||||
|
tSerializer: KSerializer<T>,
|
||||||
|
builder: (JsonElement) -> T
|
||||||
|
): DeserializationStrategy<T> = object :
|
||||||
|
DeserializationStrategy<T> {
|
||||||
|
private val jsonElementSerializer = JsonElement.serializer()
|
||||||
|
|
||||||
|
override val descriptor: SerialDescriptor
|
||||||
|
get() = jsonElementSerializer.descriptor
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): T {
|
||||||
|
val json = decoder.decodeSerializableValue(jsonElementSerializer)
|
||||||
|
return builder(json)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Json encoded TObject
|
||||||
|
*/
|
||||||
|
public fun <T : TObject> TObject.decodeFromJson(serializer: KSerializer<T>, jsonElement: JsonElement): T =
|
||||||
|
RootDecoder.decode(serializer, jsonElement)
|
||||||
|
|
||||||
|
public fun <T : TObject> TObject.decodeFromString(serializer: KSerializer<T>, string: String): T {
|
||||||
|
val json = Json.parseToJsonElement(string)
|
||||||
|
return RootDecoder.decode(serializer, json)
|
||||||
|
}
|
||||||
|
|
||||||
|
private object RootDecoder {
|
||||||
|
|
||||||
|
private class RootUnrefSerializer<T>(
|
||||||
|
private val tSerializer: KSerializer<T>,
|
||||||
|
private val refCache: List<RefEntry>,
|
||||||
|
) : KSerializer<T> by tSerializer {
|
||||||
|
|
||||||
|
override fun deserialize(decoder: Decoder): T {
|
||||||
|
val input = decoder as JsonDecoder
|
||||||
|
val element = input.decodeJsonElement()
|
||||||
|
val refId = (element as? JsonObject)?.get("\$ref")?.jsonPrimitive?.int
|
||||||
|
val ref = if (refId != null) {
|
||||||
|
println("Substituting ${tSerializer.descriptor.serialName} ref $refId")
|
||||||
|
//Forward ref for shapes
|
||||||
|
when (tSerializer.descriptor.serialName) {
|
||||||
|
"TGeoShape" -> return TGeoShapeRef {
|
||||||
|
refCache[refId].getOrPutValue {
|
||||||
|
input.json.decodeFromJsonElement(tSerializer, it) as TGeoShape
|
||||||
|
}
|
||||||
|
} as T
|
||||||
|
|
||||||
|
"TGeoVolumeAssembly" -> return TGeoVolumeAssemblyRef {
|
||||||
|
refCache[refId].getOrPutValue {
|
||||||
|
input.json.decodeFromJsonElement(tSerializer, it) as TGeoVolumeAssembly
|
||||||
|
}
|
||||||
|
} as T
|
||||||
|
|
||||||
|
"TGeoVolume" -> return TGeoVolumeRef {
|
||||||
|
refCache[refId].getOrPutValue {
|
||||||
|
input.json.decodeFromJsonElement(tSerializer, it) as TGeoVolume
|
||||||
|
}
|
||||||
|
} as T
|
||||||
|
|
||||||
|
//Do unref
|
||||||
|
else -> refCache[refId]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
refCache.find { it.element == element } ?: error("Element '$element' not found in the cache")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ref.getOrPutValue {
|
||||||
|
// println("Decoding $it")
|
||||||
|
val actualTypeName = it.jsonObject["_typename"]?.jsonPrimitive?.content
|
||||||
|
input.json.decodeFromJsonElement(tSerializer, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> KSerializer<T>.unref(refCache: List<RefEntry>): KSerializer<T> = RootUnrefSerializer(this, refCache)
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
|
fun unrefSerializersModule(
|
||||||
|
refCache: List<RefEntry>
|
||||||
|
): SerializersModule = SerializersModule {
|
||||||
|
|
||||||
|
contextual(TObjArray::class) {
|
||||||
|
TObjArray.serializer(it[0]).unref(refCache)
|
||||||
|
}
|
||||||
|
|
||||||
|
contextual(TGeoMedium.serializer().unref(refCache))
|
||||||
|
|
||||||
|
polymorphic(TGeoBoolNode::class) {
|
||||||
|
subclass(TGeoIntersection.serializer().unref(refCache))
|
||||||
|
subclass(TGeoUnion.serializer().unref(refCache))
|
||||||
|
subclass(TGeoSubtraction.serializer().unref(refCache))
|
||||||
|
}
|
||||||
|
|
||||||
|
polymorphic(TGeoShape::class) {
|
||||||
|
subclass(TGeoBBox.serializer())
|
||||||
|
subclass(TGeoXtru.serializer())
|
||||||
|
subclass(TGeoTube.serializer())
|
||||||
|
subclass(TGeoTubeSeg.serializer())
|
||||||
|
subclass(TGeoPcon.serializer())
|
||||||
|
subclass(TGeoPgon.serializer())
|
||||||
|
|
||||||
|
subclass(TGeoCompositeShape.serializer().unref(refCache))
|
||||||
|
subclass(TGeoShapeAssembly.serializer().unref(refCache))
|
||||||
|
|
||||||
|
default {
|
||||||
|
if (it == null) {
|
||||||
|
TGeoShape.serializer().unref(refCache)
|
||||||
|
} else {
|
||||||
|
error("Unrecognized shape $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
polymorphic(TGeoMatrix::class) {
|
||||||
|
subclass(TGeoIdentity.serializer())
|
||||||
|
subclass(TGeoHMatrix.serializer().unref(refCache))
|
||||||
|
subclass(TGeoTranslation.serializer())
|
||||||
|
subclass(TGeoRotation.serializer())
|
||||||
|
subclass(TGeoCombiTrans.serializer().unref(refCache))
|
||||||
|
|
||||||
|
|
||||||
|
val unrefed = TGeoMatrix.serializer().unref(refCache)
|
||||||
|
default {
|
||||||
|
if (it == null) {
|
||||||
|
unrefed
|
||||||
|
} else {
|
||||||
|
error("Unrecognized matrix $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
polymorphic(TGeoVolume::class, TGeoVolume.serializer().unref(refCache)) {
|
||||||
|
subclass(TGeoVolumeAssembly.serializer().unref(refCache))
|
||||||
|
|
||||||
|
val unrefed = TGeoVolume.serializer().unref(refCache)
|
||||||
|
default {
|
||||||
|
if (it == null) {
|
||||||
|
unrefed
|
||||||
|
} else {
|
||||||
|
error("Unrecognized volume $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
polymorphic(TGeoNode::class, TGeoNode.serializer().unref(refCache)) {
|
||||||
|
subclass(TGeoNodeMatrix.serializer().unref(refCache))
|
||||||
|
subclass(TGeoNodeOffset.serializer().unref(refCache))
|
||||||
|
|
||||||
|
val unrefed = TGeoNode.serializer().unref(refCache)
|
||||||
|
default {
|
||||||
|
if (it == null) {
|
||||||
|
unrefed
|
||||||
|
} else {
|
||||||
|
error("Unrecognized node $it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance of Json with unfolding Root references. This instance could not be reused because of the cache.
|
||||||
|
*/
|
||||||
|
private fun unrefJson(refCache: MutableList<RefEntry>): Json = Json {
|
||||||
|
encodeDefaults = true
|
||||||
|
ignoreUnknownKeys = true
|
||||||
|
classDiscriminator = "_typename"
|
||||||
|
serializersModule = unrefSerializersModule(refCache)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun <T : TObject> decode(sourceDeserializer: KSerializer<T>, source: JsonElement): T {
|
||||||
|
val refCache = ArrayList<RefEntry>()
|
||||||
|
|
||||||
|
fun fillCache(element: JsonElement) {
|
||||||
|
when (element) {
|
||||||
|
is JsonObject -> {
|
||||||
|
if (element["_typename"] != null) {
|
||||||
|
refCache.add(RefEntry(element))
|
||||||
|
}
|
||||||
|
element.values.forEach {
|
||||||
|
fillCache(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is JsonArray -> {
|
||||||
|
element.forEach {
|
||||||
|
fillCache(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
//ignore primitives
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fillCache(source)
|
||||||
|
|
||||||
|
return unrefJson(refCache).decodeFromJsonElement(sourceDeserializer.unref(refCache), source)
|
||||||
|
}
|
||||||
|
|
||||||
|
class RefEntry(val element: JsonElement) {
|
||||||
|
|
||||||
|
var value: Any? = null
|
||||||
|
|
||||||
|
fun <T> getOrPutValue(builder: (JsonElement) -> T): T {
|
||||||
|
if (value == null) {
|
||||||
|
value = builder(element)
|
||||||
|
}
|
||||||
|
return value as T
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = element.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
// val json = Json {
|
||||||
|
// encodeDefaults = true
|
||||||
|
// ignoreUnknownKeys = true
|
||||||
|
// classDiscriminator = "_typename"
|
||||||
|
// serializersModule = this@RootDecoder.serializersModule
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root.serialization
|
||||||
|
|
||||||
import space.kscience.dataforge.names.Name
|
import space.kscience.dataforge.names.Name
|
||||||
import space.kscience.dataforge.names.asName
|
import space.kscience.dataforge.names.asName
|
@ -1,12 +1,16 @@
|
|||||||
package ru.mipt.npm.root
|
package ru.mipt.npm.root
|
||||||
|
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.JsonArray
|
||||||
|
import kotlinx.serialization.json.JsonElement
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import ru.mipt.npm.root.serialization.TGeoManager
|
||||||
import space.kscience.visionforge.solid.Solids
|
import space.kscience.visionforge.solid.Solids
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
private fun JsonElement.countTypes(): Sequence<String> = sequence {
|
private fun JsonElement.countTypes(): Sequence<String> = sequence {
|
||||||
when (val json = this@countTypes){
|
when (val json = this@countTypes) {
|
||||||
is JsonObject -> {
|
is JsonObject -> {
|
||||||
json["_typename"]?.let { yield(it.jsonPrimitive.content) }
|
json["_typename"]?.let { yield(it.jsonPrimitive.content) }
|
||||||
json.values.forEach { yieldAll(it.countTypes()) }
|
json.values.forEach { yieldAll(it.countTypes()) }
|
||||||
@ -16,25 +20,33 @@ private fun JsonElement.countTypes(): Sequence<String> = sequence {
|
|||||||
yieldAll(it.countTypes())
|
yieldAll(it.countTypes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val string = TGeoManager::class.java.getResourceAsStream("/BM@N.root.json")!!
|
val string = TGeoManager::class.java.getResourceAsStream("/BM@N.root.json")!!
|
||||||
.readAllBytes().decodeToString()
|
.readAllBytes().decodeToString()
|
||||||
val json = Json.parseToJsonElement(string)
|
|
||||||
val sizes = json.countTypes().groupBy { it }.mapValues { it.value.size }
|
|
||||||
sizes.forEach {
|
|
||||||
println(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
val time = measureTimeMillis {
|
val time = measureTimeMillis {
|
||||||
val geo = TObject.decodeFromString(TGeoManager.serializer(), string)
|
val geo = TGeoManagerScheme.parse(string)
|
||||||
val solid = geo.toSolid()
|
val solid = geo.toSolid()
|
||||||
|
|
||||||
println(Solids.encodeToString(solid))
|
println(Solids.encodeToString(solid))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// val json = Json.parseToJsonElement(string)
|
||||||
|
// val sizes = json.countTypes().groupBy { it }.mapValues { it.value.size }
|
||||||
|
// sizes.forEach {
|
||||||
|
// println(it)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val time = measureTimeMillis {
|
||||||
|
// val geo = TObject.decodeFromString(TGeoManager.serializer(), string)
|
||||||
|
// val solid = geo.toSolid()
|
||||||
|
//
|
||||||
|
// println(Solids.encodeToString(solid))
|
||||||
|
// }
|
||||||
|
//
|
||||||
println(Duration.ofMillis(time))
|
println(Duration.ofMillis(time))
|
||||||
}
|
}
|
@ -1,7 +1,5 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
|
||||||
kotlin.mpp.stability.nowarn=true
|
kotlin.mpp.stability.nowarn=true
|
||||||
kotlin.native.enableDependencyPropagation=false
|
|
||||||
|
|
||||||
#kotlin.jupyter.add.scanner=false
|
#kotlin.jupyter.add.scanner=false
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user