feature/root #69

Merged
altavir merged 23 commits from feature/root into dev 2021-09-11 19:14:21 +03:00
10 changed files with 200 additions and 184 deletions
Showing only changes of commit bdbe940272 - Show all commits

View File

@ -16,7 +16,7 @@ allprojects {
} }
group = "space.kscience" group = "space.kscience"
version = "0.2.0-dev-23" version = "0.2.0-dev-24"
} }
subprojects { subprojects {

View File

@ -15,7 +15,6 @@ public fun MetaProvider.doubleArray(
it?.doubleArray ?: doubleArrayOf(*default) it?.doubleArray ?: doubleArrayOf(*default)
} }
public class DObjectCache(private val cache: List<Meta>, public val refStack: List<Int> = emptyList()) { public class DObjectCache(private val cache: List<Meta>, public val refStack: List<Int> = emptyList()) {
public operator fun get(index: Int): Meta = cache[index] public operator fun get(index: Int): Meta = cache[index]
@ -25,28 +24,6 @@ public class DObjectCache(private val cache: List<Meta>, public val refStack: Li
public val empty: DObjectCache = DObjectCache(emptyList(), emptyList()) public val empty: DObjectCache = DObjectCache(emptyList(), emptyList())
} }
} }
//
//public interface ObjectRef<T : DObject> {
// public fun resolve(): T?
//}
//public class ChildObjectRef<T : DObject>(
// public val builder: (Meta, DObjectCache) -> T,
// public val refCache: DObjectCache,
// public val metaProvider: () -> Meta?
//) : ObjectRef<T> {
// override fun resolve(): T? {
// val meta = metaProvider() ?: return null
// meta["\$ref"]?.int?.let { refId ->
// if (refCache.refStack.contains(refId)) {
// println("Circular reference $refId in stack ${refCache.refStack}")
// return null
// }
// return builder(refCache[refId], refCache.stack(refId))
// }
// return builder(meta, refCache)
// }
//}
public open class DObject(public val meta: Meta, private val refCache: DObjectCache) { public open class DObject(public val meta: Meta, private val refCache: DObjectCache) {

View File

@ -4,6 +4,7 @@ import space.kscience.dataforge.meta.*
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.plus import space.kscience.dataforge.names.plus
import space.kscience.dataforge.values.doubleArray import space.kscience.dataforge.values.doubleArray
import space.kscience.visionforge.isEmpty
import space.kscience.visionforge.solid.* import space.kscience.visionforge.solid.*
import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY import space.kscience.visionforge.solid.SolidMaterial.Companion.MATERIAL_COLOR_KEY
import kotlin.math.* import kotlin.math.*
@ -16,7 +17,16 @@ private operator fun Number.times(f: Float) = toFloat() * f
private fun degToRad(d: Double) = d * PI / 180.0 private fun degToRad(d: Double) = d * PI / 180.0
private class RootToSolidContext(val prototypeHolder: PrototypeHolder) private class RootToSolidContext(val prototypeHolder: PrototypeHolder, val maxLayer: Int = 3) {
val layers: MutableList<Int> = mutableListOf(0)
val layerLimits = listOf(10_000, 25_000, 50_000, 100_000, 200_000, 400_000, 600_000)
val bottomLayer: Int get() = layers.size - 1
fun addLayer() {
layers.add(0)
}
}
// converting to XYZ to TaitBryan angles according to https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix // converting to XYZ to TaitBryan angles according to https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
private fun Solid.rotate(rot: DoubleArray) { private fun Solid.rotate(rot: DoubleArray) {
@ -67,8 +77,10 @@ private fun Solid.useMatrix(matrix: DGeoMatrix?) {
private fun SolidGroup.addShape( private fun SolidGroup.addShape(
shape: DGeoShape, shape: DGeoShape,
context: RootToSolidContext, context: RootToSolidContext,
name: String? = shape.fName.ifEmpty { null } name: String? = shape.fName.ifEmpty { null },
): Solid? = when (shape.typename) { block: Solid.() -> Unit = {}
) {
when (shape.typename) {
"TGeoCompositeShape" -> { "TGeoCompositeShape" -> {
val fNode: DGeoBoolNode? by shape.dObject(::DGeoBoolNode) val fNode: DGeoBoolNode? by shape.dObject(::DGeoBoolNode)
val node = fNode ?: error("Composite shape node not resolved") val node = fNode ?: error("Composite shape node not resolved")
@ -79,15 +91,13 @@ private fun SolidGroup.addShape(
else -> error("Unknown bool node type ${node.typename}") else -> error("Unknown bool node type ${node.typename}")
} }
smartComposite(compositeType, name = name) { smartComposite(compositeType, name = name) {
addShape(node.fLeft!!, context, null).also { addShape(node.fLeft!!, context, null) {
if (it == null) TODO() this.useMatrix(node.fLeftMat)
it.useMatrix(node.fLeftMat)
}
addShape(node.fRight!!, context, null).also {
if (it == null) TODO()
it.useMatrix(node.fRightMat)
} }
addShape(node.fRight!!, context, null) {
this.useMatrix(node.fRightMat)
} }
}.apply(block)
} }
"TGeoXtru" -> { "TGeoXtru" -> {
val fNvert by shape.meta.int(0) val fNvert by shape.meta.int(0)
@ -114,7 +124,7 @@ private fun SolidGroup.addShape(
fScale[index] fScale[index]
) )
} }
} }.apply(block)
} }
"TGeoTube" -> { "TGeoTube" -> {
val fRmax by shape.meta.double(0.0) val fRmax by shape.meta.double(0.0)
@ -125,7 +135,8 @@ private fun SolidGroup.addShape(
radius = fRmax, radius = fRmax,
height = fDz * 2, height = fDz * 2,
innerRadius = fRmin, innerRadius = fRmin,
name = name name = name,
block = block
) )
} }
"TGeoTubeSeg" -> { "TGeoTubeSeg" -> {
@ -141,7 +152,8 @@ private fun SolidGroup.addShape(
innerRadius = fRmin, innerRadius = fRmin,
startAngle = degToRad(fPhi1), startAngle = degToRad(fPhi1),
angle = degToRad(fPhi2 - fPhi1), angle = degToRad(fPhi2 - fPhi1),
name = name name = name,
block = block
) )
} }
"TGeoPcon" -> { "TGeoPcon" -> {
@ -160,10 +172,11 @@ private fun SolidGroup.addShape(
topInnerRadius = fRmin[1], topInnerRadius = fRmin[1],
startAngle = degToRad(fPhi1), startAngle = degToRad(fPhi1),
angle = degToRad(fDphi), angle = degToRad(fDphi),
name = name name = name,
) { ) {
z = (fZ[1] + fZ[0]) / 2 z = (fZ[1] + fZ[0]) / 2
}
}.apply(block)
} else { } else {
TODO() TODO()
} }
@ -195,29 +208,33 @@ private fun SolidGroup.addShape(
//scaling all radii relative to first layer radius //scaling all radii relative to first layer radius
layer(fZ[index], scale = fRmax[index] / baseRadius) layer(fZ[index], scale = fRmax[index] / baseRadius)
} }
} }.apply(block)
} }
"TGeoShapeAssembly" -> { "TGeoShapeAssembly" -> {
val fVolume by shape.dObject(::DGeoVolume) val fVolume by shape.dObject(::DGeoVolume)
fVolume?.let { volume -> fVolume?.let { volume ->
addRootVolume(volume, context) addRootVolume(volume, context, block = block)
} }
} }
"TGeoBBox" -> { "TGeoBBox" -> {
box(shape.fDX * 2, shape.fDY * 2, shape.fDZ * 2, name = name) box(shape.fDX * 2, shape.fDY * 2, shape.fDZ * 2, name = name, block = block)
} }
else -> { else -> {
TODO("A shape with type ${shape.typename} not implemented") TODO("A shape with type ${shape.typename} not implemented")
} }
}
} }
private fun SolidGroup.addRootNode(obj: DGeoNode, context: RootToSolidContext) { private fun SolidGroup.addRootNode(obj: DGeoNode, context: RootToSolidContext) {
val volume = obj.fVolume ?: return val volume = obj.fVolume ?: return
addRootVolume(volume, context, obj.fName).apply { addRootVolume(volume, context, obj.fName) {
if (context.bottomLayer > 0) {
this.layer = context.bottomLayer
}
when (obj.typename) { when (obj.typename) {
"TGeoNodeMatrix" -> { "TGeoNodeMatrix" -> {
val fMatrix by obj.dObject(::DGeoMatrix) val fMatrix by obj.dObject(::DGeoMatrix)
useMatrix(fMatrix) this.useMatrix(fMatrix)
} }
"TGeoNodeOffset" -> { "TGeoNodeOffset" -> {
val fOffset by obj.meta.double(0.0) val fOffset by obj.meta.double(0.0)
@ -227,19 +244,29 @@ private fun SolidGroup.addRootNode(obj: DGeoNode, context: RootToSolidContext) {
} }
} }
private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid { private fun buildVolume(volume: DGeoVolume, context: RootToSolidContext): Solid? {
val group = SolidGroup { val group = SolidGroup {
if(volume.fNodes.isEmpty()) { val nodesNum = volume.fNodes.size
if (nodesNum == 0) {
//TODO add smart filter //TODO add smart filter
volume.fShape?.let { shape -> volume.fShape?.let { shape ->
addShape(shape, context) addShape(shape, context)
} }
} }
val expectedLayerSize = context.layers.last() + nodesNum
//If expected number exceeds layer limit, move everything else to the bottom layer.
if (expectedLayerSize >= context.layerLimits[context.bottomLayer]) {
context.addLayer()
println("Adding new layer. Sizes after add: ${context.layers}")
}
context.layers[context.bottomLayer] += nodesNum
volume.fNodes.forEach { node -> volume.fNodes.forEach { node ->
addRootNode(node, context) addRootNode(node, context)
} }
} }
return if (group.children.size == 1 && group.meta.isEmpty()) { return if (group.isEmpty()) {
null
} else if (group.children.size == 1 && group.meta.isEmpty()) {
(group.children.values.first() as Solid).apply { parent = null } (group.children.values.first() as Solid).apply { parent = null }
} else { } else {
group group
@ -252,8 +279,15 @@ private fun SolidGroup.addRootVolume(
volume: DGeoVolume, volume: DGeoVolume,
context: RootToSolidContext, context: RootToSolidContext,
name: String? = null, name: String? = null,
cache: Boolean = true cache: Boolean = true,
): Solid { block: Solid.() -> Unit = {}
) {
//skip if maximum layer number is reached
if (context.bottomLayer > context.maxLayer){
println("Maximum layer depth reached. Skipping ${volume.fName}")
return
}
val combinedName = if (volume.fName.isEmpty()) { val combinedName = if (volume.fName.isEmpty()) {
name name
} else if (name == null) { } else if (name == null) {
@ -262,24 +296,30 @@ private fun SolidGroup.addRootVolume(
"${name}_${volume.fName}" "${name}_${volume.fName}"
} }
return if (!cache) { if (!cache) {
val group = buildVolume(volume, context) val group = buildVolume(volume, context)?.apply {
volume.fFillColor?.let {
meta[MATERIAL_COLOR_KEY] = RootColors[it]
}
block()
}
set(combinedName?.let { Name.parse(it) }, group) set(combinedName?.let { Name.parse(it) }, group)
group
} else { } else {
val templateName = volumesName + volume.name val templateName = volumesName + volume.name
val existing = getPrototype(templateName) val existing = getPrototype(templateName)
if (existing == null) { if (existing == null) {
context.prototypeHolder.prototypes { context.prototypeHolder.prototypes {
set(templateName, buildVolume(volume, context)) val group = buildVolume(volume, context)
set(templateName, group)
} }
} }
ref(templateName, name) ref(templateName, name).apply {
}.apply {
volume.fFillColor?.let { volume.fFillColor?.let {
meta[MATERIAL_COLOR_KEY] = RootColors[it] meta[MATERIAL_COLOR_KEY] = RootColors[it]
} }
block()
}
} }
} }

View File

@ -65,12 +65,6 @@ application {
mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt") mainClass.set("ru.mipt.npm.muon.monitor.server.MMServerKt")
} }
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJsCompile>() {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + "-Xir-property-lazy-initialization"
}
}
//distributions { //distributions {
// main { // main {
// contents { // contents {

View File

@ -9,6 +9,8 @@ import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.isLeaf import space.kscience.dataforge.meta.isLeaf
import space.kscience.dataforge.values.string import space.kscience.dataforge.values.string
import space.kscience.visionforge.solid.Solids import space.kscience.visionforge.solid.Solids
import java.nio.file.Paths
import kotlin.io.path.writeText
private fun Meta.countTypes(): Sequence<String> = sequence { private fun Meta.countTypes(): Sequence<String> = sequence {
@ -37,12 +39,18 @@ fun main() {
val solid = geo.toSolid() val solid = geo.toSolid()
//Paths.get("BM@N.vf.json").writeText(Solids.encodeToString(solid)) Paths.get("BM@N.vf.json").writeText(Solids.encodeToString(solid))
//println(Solids.encodeToString(solid)) //println(Solids.encodeToString(solid))
context.makeVisionFile { context.makeVisionFile {
vision("canvas") { vision("canvas") {
solid solid
}
}
}
/* SolidGroup { /* SolidGroup {
set( set(
"Coil", "Coil",
@ -99,6 +107,3 @@ fun main() {
} }
}*//* }*//*
}*/ }*/
}
}
}

View File

@ -2,7 +2,7 @@ kotlin.code.style=official
kotlin.mpp.stability.nowarn=true kotlin.mpp.stability.nowarn=true
#kotlin.jupyter.add.scanner=false #kotlin.jupyter.add.scanner=false
kotlin.incremental.js.klib=false #kotlin.incremental.js.klib=false
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G org.gradle.jvmargs=-XX:MaxMetaspaceSize=1G
org.gradle.parallel=true org.gradle.parallel=true

View File

@ -83,7 +83,7 @@ private fun RBuilder.visionTree(props: ObjectTreeProps): Unit {
} }
obj.children.entries obj.children.entries
.filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children .filter { !it.key.toString().startsWith("@") } // ignore statics and other hidden children
.sortedBy { (it.value as? VisionGroup)?.isEmpty ?: true } // ignore empty groups .sortedBy { (it.value as? VisionGroup)?.isEmpty() ?: true } // ignore empty groups
.forEach { (childToken, child) -> .forEach { (childToken, child) ->
styledDiv { styledDiv {
css { css {

View File

@ -63,7 +63,7 @@ public interface VisionGroup : Provider, Vision, VisionContainer<Vision> {
*/ */
public operator fun VisionGroup.iterator(): Iterator<Vision> = children.values.iterator() public operator fun VisionGroup.iterator(): Iterator<Vision> = children.values.iterator()
public val VisionGroup.isEmpty: Boolean get() = this.children.isEmpty() public fun VisionGroup.isEmpty(): Boolean = this.children.isEmpty()
public interface VisionContainerBuilder<in V : Vision> { public interface VisionContainerBuilder<in V : Vision> {
//TODO add documentation //TODO add documentation

View File

@ -67,8 +67,8 @@ internal fun checkOrStoreFile(htmlPath: Path, filePath: Path, resource: String):
if (!skip) { if (!skip) {
logger.debug("File $fullPath does not exist or wrong checksum. Writing file") logger.debug("File $fullPath does not exist or wrong checksum. Writing file")
Files.createDirectories(fullPath.parent) Files.createDirectories(fullPath.parent)
Files.write(fullPath, bytes, StandardOpenOption.CREATE, StandardOpenOption.WRITE) Files.write(fullPath, bytes, StandardOpenOption.CREATE,StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)
Files.write(md5File, checksum.encodeToByteArray(), StandardOpenOption.CREATE, StandardOpenOption.WRITE) Files.write(md5File, checksum.encodeToByteArray(), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE)
} }
return if (htmlPath.isAbsolute && fullPath.startsWith(htmlPath.parent)) { return if (htmlPath.isAbsolute && fullPath.startsWith(htmlPath.parent)) {

View File

@ -57,8 +57,8 @@ public inline fun VisionContainerBuilder<Solid>.box(
ySize: Number, ySize: Number,
zSize: Number, zSize: Number,
name: String? = null, name: String? = null,
action: Box.() -> Unit = {}, block: Box.() -> Unit = {},
): Box = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(action).also { set(name, it) } ): Box = Box(xSize.toFloat(), ySize.toFloat(), zSize.toFloat()).apply(block).also { set(name, it) }
@Serializable @Serializable
@SerialName("solid.hexagon") @SerialName("solid.hexagon")