add rebalance and fix range issues
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
3d28b369f2
commit
ff5c65765e
4 changed files with 13 additions and 3 deletions
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue