add rebalance and fix range issues
continuous-integration/drone/push Build is passing Details

master
eater 4 years ago
parent 3d28b369f2
commit ff5c65765e
Signed by: eater
GPG Key ID: AD2560A0F84F0759

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

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

@ -7,7 +7,7 @@ import me.eater.threedom.utils.joml.compareTo
import me.eater.threedom.utils.joml.getTranslation
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>()
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 median = sorted.size / 2
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)
}?.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)
}?.let { create(it, depth + 1) }
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) }
add(node)
}
fun rebalance() {
root = Node.create(nodeLocMap.entries.groupBy({ it.value }) { it.key })
}
}

@ -38,6 +38,10 @@ class PositionTest : StringSpec({
nodeTwo.model { setTranslation(-10, 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(0, 20, 10) shouldHaveSingleElement nodeTwo
doc.findAt(0, 40, 10) shouldHaveSingleElement nodeThree

Loading…
Cancel
Save