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.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)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user