layer marking

This commit is contained in:
Alexander Nozik 2021-07-14 15:45:01 +03:00
parent f2e7e16d62
commit 8f95d6f485
6 changed files with 75 additions and 39 deletions

View File

@ -10,6 +10,7 @@ import space.kscience.dataforge.context.fetch
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.gdml.Gdml import space.kscience.gdml.Gdml
import space.kscience.gdml.decodeFromString import space.kscience.gdml.decodeFromString
import space.kscience.visionforge.gdml.markLayers
import space.kscience.visionforge.gdml.toVision import space.kscience.visionforge.gdml.toVision
import space.kscience.visionforge.ring.ThreeCanvasWithControls import space.kscience.visionforge.ring.ThreeCanvasWithControls
import space.kscience.visionforge.ring.tab import space.kscience.visionforge.ring.tab
@ -33,8 +34,9 @@ val GDMLApp = functionalComponent<GDMLAppProps>("GDMLApp") { props ->
name.endsWith(".gdml") || name.endsWith(".xml") -> { name.endsWith(".gdml") || name.endsWith(".xml") -> {
val gdml = Gdml.decodeFromString(data) val gdml = Gdml.decodeFromString(data)
gdml.toVision().apply { gdml.toVision().apply {
// console.info("Marking layers for file $name") root(visionManager)
// markLayers() console.info("Marking layers for file $name")
markLayers()
} }
} }
name.endsWith(".json") -> visionManager.decodeFromString(data) name.endsWith(".json") -> visionManager.decodeFromString(data)

View File

@ -1,5 +1,7 @@
package space.kscience.visionforge.gdml package space.kscience.visionforge.gdml
import space.kscience.dataforge.context.info
import space.kscience.dataforge.context.logger
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.length import space.kscience.dataforge.names.length
@ -7,24 +9,36 @@ import space.kscience.dataforge.names.plus
import space.kscience.visionforge.VisionGroup import space.kscience.visionforge.VisionGroup
import space.kscience.visionforge.solid.Solid import space.kscience.visionforge.solid.Solid
import space.kscience.visionforge.solid.SolidGroup import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.SolidReferenceGroup
import space.kscience.visionforge.solid.layer import space.kscience.visionforge.solid.layer
private class VisionCounterTree( private class VisionCounterTree(
val name: Name, val name: Name,
val vision: Solid, val vision: Solid,
val prototypes: HashMap<Name, VisionCounterTree>
) { ) {
val children: Map<NameToken, VisionCounterTree> =
(vision as? VisionGroup)?.children?.mapValues { // self count for prototypes
VisionCounterTree(name + it.key, it.value as Solid) var selfCount = 1
val children: Map<NameToken, VisionCounterTree> by lazy {
(vision as? VisionGroup)?.children?.mapValues { (key, vision) ->
if (vision is SolidReferenceGroup) {
prototypes.getOrPut(vision.refName) {
VisionCounterTree(vision.refName, vision.prototype, prototypes)
}.apply {
selfCount += 1
}
} else {
VisionCounterTree(name + key, vision as Solid, prototypes)
}
} ?: emptyMap() } ?: emptyMap()
}
// val childrenCount: Int by lazy {
// val directChildrenCount: Int by lazy {
// children.size
// }
val childrenCount: Int =
children.values.sumOf { it.childrenCount + 1 } children.values.sumOf { it.childrenCount + 1 }
}
} }
@ -36,27 +50,41 @@ private fun VisionCounterTree.topToBottom(): Sequence<VisionCounterTree> = seque
} }
} }
public fun SolidGroup.markLayers(thresholds: List<Int> = listOf(1000, 20000, 100000)) { public fun SolidGroup.markLayers(thresholds: List<Int> = listOf(500, 1000, 20000, 50000)) {
val counterTree = VisionCounterTree(Name.EMPTY, this) val logger = manager?.context?.logger
val counterTree = VisionCounterTree(Name.EMPTY, this, hashMapOf())
val totalCount = counterTree.childrenCount val totalCount = counterTree.childrenCount
if (totalCount > thresholds.firstOrNull() ?: 0) { if (totalCount > thresholds.firstOrNull() ?: 0) {
val allNodes = counterTree.topToBottom().toMutableList() val allNodes = counterTree.topToBottom().filter { it.selfCount > 1 }.distinct().toMutableList()
//println("tree construction finished") //println("tree construction finished")
allNodes.sortWith(compareBy<VisionCounterTree>({ it.name.length }, { it.childrenCount }).reversed()) allNodes.sortWith(
compareBy<VisionCounterTree>(
{ it.name.length },
{ it.childrenCount * it.selfCount }
).reversed()
)
//mark layers //mark layers
var removed = 0 var remaining = totalCount
var thresholdIndex = thresholds.indexOfLast { it < totalCount }
for (node in allNodes) { for (node in allNodes) {
node.vision.layer = thresholdIndex + 1 val layerIndex = if (remaining > thresholds.last())
removed++ thresholds.size
if (totalCount - removed < thresholds[thresholdIndex]) { else
thresholdIndex-- thresholds.indexOfLast { remaining < it }
}
if (thresholdIndex < 0) break
}
if (layerIndex == 0) break
node.vision.layer = layerIndex
val removedCount = node.selfCount * node.children.size
logger?.apply {
if (node.selfCount > 1) {
info { "Prototype with name ${node.name} moved to layer $layerIndex" }
} else {
info { "Vision with name ${node.name} moved to layer $layerIndex" }
}
}
remaining -= removedCount
}
} }
} }

View File

@ -99,15 +99,15 @@ public class SolidReferenceGroup(
*/ */
private class ReferenceChild( private class ReferenceChild(
val owner: SolidReferenceGroup, val owner: SolidReferenceGroup,
private val childName: Name private val refName: Name
) : SolidReference, VisionGroup, Solid { ) : SolidReference, VisionGroup, Solid {
override val prototype: Solid by lazy { override val prototype: Solid by lazy {
if (childName.isEmpty()) owner.prototype else { if (refName.isEmpty()) owner.prototype else {
val proto = (owner.prototype as? VisionGroup)?.get(childName) val proto = (owner.prototype as? VisionGroup)?.get(refName)
?: error("Prototype with name $childName not found in SolidReferenceGroup ${owner.refName}") ?: error("Prototype with name $refName not found in SolidReferenceGroup ${owner.refName}")
proto.unref as? Solid proto.unref as? Solid
?: error("Prototype with name $childName is ${proto::class} but expected Solid") ?: error("Prototype with name $refName is ${proto::class} but expected Solid")
} }
} }
@ -115,14 +115,14 @@ public class SolidReferenceGroup(
get() = (prototype as? VisionGroup)?.children get() = (prototype as? VisionGroup)?.children
?.filter { it.key != SolidGroup.PROTOTYPES_TOKEN } ?.filter { it.key != SolidGroup.PROTOTYPES_TOKEN }
?.mapValues { (key, _) -> ?.mapValues { (key, _) ->
ReferenceChild(owner, childName + key.asName()) ReferenceChild(owner, refName + key.asName())
} ?: emptyMap() } ?: emptyMap()
override fun getOwnProperty(name: Name): MetaItem? = override fun getOwnProperty(name: Name): MetaItem? =
owner.getOwnProperty(childPropertyName(childName, name)) owner.getOwnProperty(childPropertyName(refName, name))
override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) { override fun setProperty(name: Name, item: MetaItem?, notify: Boolean) {
owner.setProperty(childPropertyName(childName, name), item, notify) owner.setProperty(childPropertyName(refName, name), item, notify)
} }
override fun getProperty( override fun getProperty(
@ -134,7 +134,7 @@ public class SolidReferenceGroup(
override var parent: VisionGroup? override var parent: VisionGroup?
get() { get() {
val parentName = childName.cutLast() val parentName = refName.cutLast()
return if (parentName.isEmpty()) owner else ReferenceChild(owner, parentName) return if (parentName.isEmpty()) owner else ReferenceChild(owner, parentName)
} }
set(_) { set(_) {
@ -144,7 +144,7 @@ public class SolidReferenceGroup(
@DFExperimental @DFExperimental
override val propertyChanges: Flow<Name> override val propertyChanges: Flow<Name>
get() = owner.propertyChanges.mapNotNull { name -> get() = owner.propertyChanges.mapNotNull { name ->
if (name.startsWith(childToken(childName))) { if (name.startsWith(childToken(refName))) {
name.cutFirst() name.cutFirst()
} else { } else {
null null
@ -152,7 +152,7 @@ public class SolidReferenceGroup(
} }
override fun invalidateProperty(propertyName: Name) { override fun invalidateProperty(propertyName: Name) {
owner.invalidateProperty(childPropertyName(childName, propertyName)) owner.invalidateProperty(childPropertyName(refName, propertyName))
} }
override fun update(change: VisionChange) { override fun update(change: VisionChange) {

View File

@ -74,9 +74,9 @@ internal fun Mesh.applyProperties(obj: Solid): Mesh = apply {
updateMaterial(obj) updateMaterial(obj)
applyEdges(obj) applyEdges(obj)
//applyWireFrame(obj) //applyWireFrame(obj)
layers.enable(obj.layer) layers.set(obj.layer)
children.forEach { children.forEach {
it.layers.enable(obj.layer) it.layers.set(obj.layer)
} }
} }

View File

@ -250,8 +250,11 @@ public class ThreeCanvas(
} }
public fun render(vision: Solid) { public fun render(vision: Solid) {
if (root != null) {
three.logger.info { "Replacing root node in three canvas" } three.logger.info { "Replacing root node in three canvas" }
scene.findChild("@root".asName())?.let { scene.remove(it) } scene.findChild("@root".asName())?.let { scene.remove(it) }
root?.dispose()
}
val object3D = three.buildObject3D(vision) val object3D = three.buildObject3D(vision)
object3D.name = "@root" object3D.name = "@root"

View File

@ -54,6 +54,9 @@ public class ThreeGeometryBuilder : GeometryBuilder<BufferGeometry> {
setAttribute("position", Float32BufferAttribute(positions.toTypedArray(), 3)) setAttribute("position", Float32BufferAttribute(positions.toTypedArray(), 3))
setAttribute("normal", Float32BufferAttribute(normals.toTypedArray(), 3)) setAttribute("normal", Float32BufferAttribute(normals.toTypedArray(), 3))
//setAttribute("color", Float32BufferAttribute(colors.toFloatArray(), 3)) //setAttribute("color", Float32BufferAttribute(colors.toFloatArray(), 3))
//a temporary fix for CSG problem
val uvsArray = Array<Float>((counter+1)*2){0f}
setAttribute("uv", Float32BufferAttribute(uvsArray, 2))
computeBoundingSphere() computeBoundingSphere()
} }