add rebalance and fix range issues
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
eater 2020-05-17 16:30:04 +02:00
parent 3d28b369f2
commit ff5c65765e
Signed by: eater
GPG key ID: AD2560A0F84F0759
4 changed files with 13 additions and 3 deletions

View file

@ -150,6 +150,7 @@ class Document : IDocument {
override fun getNodeByNodeId(nodeId: Long): INode<*>? = this.allNodes[nodeId] override fun getNodeByNodeId(nodeId: Long): INode<*>? = this.allNodes[nodeId]
override fun findAt(vec: Vector3dc) = kdTree.find(vec) override fun findAt(vec: Vector3dc) = kdTree.find(vec)
override fun rebalance() = kdTree.rebalance()
} }

View file

@ -13,6 +13,7 @@ interface IDocument : EventDispatcher, INodeContainer {
fun getNodeByNodeId(nodeId: Long): INode<*>? fun getNodeByNodeId(nodeId: Long): INode<*>?
fun findAt(x: Number, y: Number, z: Number) = findAt(Vector3d(x, y, z)) fun findAt(x: Number, y: Number, z: Number) = findAt(Vector3d(x, y, z))
fun findAt(vec: Vector3dc): Collection<INode<*>> fun findAt(vec: Vector3dc): Collection<INode<*>>
fun rebalance()
} }
inline fun <reified T : INode<T>> IDocument.createNode() = createNode(T::class) inline fun <reified T : INode<T>> IDocument.createNode() = createNode(T::class)

View file

@ -7,7 +7,7 @@ import me.eater.threedom.utils.joml.compareTo
import me.eater.threedom.utils.joml.getTranslation import me.eater.threedom.utils.joml.getTranslation
import org.joml.Vector3dc import org.joml.Vector3dc
class KDTree(private val document: IDocument, private val root: Node = Node(Vector3d(0, 0, 0))) { class KDTree(private val document: IDocument, private var root: Node = Node(Vector3d(0, 0, 0))) {
private val nodeLocMap = mutableMapOf<Long, Vector3dc>() private val nodeLocMap = mutableMapOf<Long, Vector3dc>()
data class Node( data class Node(
@ -89,10 +89,10 @@ class KDTree(private val document: IDocument, private val root: Node = Node(Vect
val sorted = nodes.keys.sortedBy { it[axis] } val sorted = nodes.keys.sortedBy { it[axis] }
val median = sorted.size / 2 val median = sorted.size / 2
val selected = sorted[median] val selected = sorted[median]
val left = sorted.slice(0..median).toSet().takeIf { it.isNotEmpty() }?.let { val left = sorted.slice(0 until median).toSet().takeIf { it.isNotEmpty() }?.let {
nodes.filterKeys(it::contains) nodes.filterKeys(it::contains)
}?.let { create(it, depth + 1) } }?.let { create(it, depth + 1) }
val right = sorted.slice(median + 1..sorted.size).toSet().takeIf { it.isNotEmpty() }?.let { val right = sorted.slice(median + 1 until sorted.size).toSet().takeIf { it.isNotEmpty() }?.let {
nodes.filterKeys(it::contains) nodes.filterKeys(it::contains)
}?.let { create(it, depth + 1) } }?.let { create(it, depth + 1) }
return Node(selected, nodes[selected]?.toMutableSet() ?: mutableSetOf(), depth, left, right) return Node(selected, nodes[selected]?.toMutableSet() ?: mutableSetOf(), depth, left, right)
@ -119,4 +119,8 @@ class KDTree(private val document: IDocument, private val root: Node = Node(Vect
nodeLocMap[node.nodeId]?.let { root.remove(it, node.nodeId) } nodeLocMap[node.nodeId]?.let { root.remove(it, node.nodeId) }
add(node) add(node)
} }
fun rebalance() {
root = Node.create(nodeLocMap.entries.groupBy({ it.value }) { it.key })
}
} }

View file

@ -38,6 +38,10 @@ class PositionTest : StringSpec({
nodeTwo.model { setTranslation(-10, 20, 0) } nodeTwo.model { setTranslation(-10, 20, 0) }
nodeThree.model { setTranslation(0, 20, 0) } nodeThree.model { setTranslation(0, 20, 0) }
doc.findAt(10, 0, 10) shouldHaveSingleElement node
doc.findAt(0, 20, 10) shouldHaveSingleElement nodeTwo
doc.findAt(0, 40, 10) shouldHaveSingleElement nodeThree
doc.rebalance()
doc.findAt(10, 0, 10) shouldHaveSingleElement node doc.findAt(10, 0, 10) shouldHaveSingleElement node
doc.findAt(0, 20, 10) shouldHaveSingleElement nodeTwo doc.findAt(0, 20, 10) shouldHaveSingleElement nodeTwo
doc.findAt(0, 40, 10) shouldHaveSingleElement nodeThree doc.findAt(0, 40, 10) shouldHaveSingleElement nodeThree