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

View File

@ -1,5 +1,7 @@
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.NameToken
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.solid.Solid
import space.kscience.visionforge.solid.SolidGroup
import space.kscience.visionforge.solid.SolidReferenceGroup
import space.kscience.visionforge.solid.layer
private class VisionCounterTree(
val name: Name,
val vision: Solid,
val prototypes: HashMap<Name, VisionCounterTree>
) {
val children: Map<NameToken, VisionCounterTree> =
(vision as? VisionGroup)?.children?.mapValues {
VisionCounterTree(name + it.key, it.value as Solid)
// self count for prototypes
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()
}
//
// val directChildrenCount: Int by lazy {
// children.size
// }
val childrenCount: Int =
val childrenCount: Int by lazy {
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)) {
val counterTree = VisionCounterTree(Name.EMPTY, this)
public fun SolidGroup.markLayers(thresholds: List<Int> = listOf(500, 1000, 20000, 50000)) {
val logger = manager?.context?.logger
val counterTree = VisionCounterTree(Name.EMPTY, this, hashMapOf())
val totalCount = counterTree.childrenCount
if (totalCount > thresholds.firstOrNull() ?: 0) {
val allNodes = counterTree.topToBottom().toMutableList()
val allNodes = counterTree.topToBottom().filter { it.selfCount > 1 }.distinct().toMutableList()
//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
var removed = 0
var thresholdIndex = thresholds.indexOfLast { it < totalCount }
var remaining = totalCount
for (node in allNodes) {
node.vision.layer = thresholdIndex + 1
removed++
if (totalCount - removed < thresholds[thresholdIndex]) {
thresholdIndex--
val layerIndex = if (remaining > thresholds.last())
thresholds.size
else
thresholds.indexOfLast { remaining < it }
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" }
}
}
if (thresholdIndex < 0) break
remaining -= removedCount
}
}
}

View File

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

View File

@ -74,9 +74,9 @@ internal fun Mesh.applyProperties(obj: Solid): Mesh = apply {
updateMaterial(obj)
applyEdges(obj)
//applyWireFrame(obj)
layers.enable(obj.layer)
layers.set(obj.layer)
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) {
three.logger.info { "Replacing root node in three canvas" }
scene.findChild("@root".asName())?.let { scene.remove(it) }
if (root != null) {
three.logger.info { "Replacing root node in three canvas" }
scene.findChild("@root".asName())?.let { scene.remove(it) }
root?.dispose()
}
val object3D = three.buildObject3D(vision)
object3D.name = "@root"

View File

@ -54,6 +54,9 @@ public class ThreeGeometryBuilder : GeometryBuilder<BufferGeometry> {
setAttribute("position", Float32BufferAttribute(positions.toTypedArray(), 3))
setAttribute("normal", Float32BufferAttribute(normals.toTypedArray(), 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()
}