forked from kscience/visionforge
layer marking
This commit is contained in:
parent
f2e7e16d62
commit
8f95d6f485
@ -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)
|
||||
|
@ -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--
|
||||
}
|
||||
if (thresholdIndex < 0) break
|
||||
}
|
||||
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" }
|
||||
}
|
||||
}
|
||||
remaining -= removedCount
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,8 +250,11 @@ public class ThreeCanvas(
|
||||
}
|
||||
|
||||
public fun render(vision: Solid) {
|
||||
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"
|
||||
|
@ -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()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user