This commit is contained in:
parent
4804b5c203
commit
f96da63987
4 changed files with 41 additions and 5 deletions
|
@ -152,6 +152,7 @@ class Document : IDocument {
|
||||||
override fun findAt(vec: Vector3dc) = kdTree.find(vec)
|
override fun findAt(vec: Vector3dc) = kdTree.find(vec)
|
||||||
override fun rebalance() = kdTree.rebalance()
|
override fun rebalance() = kdTree.rebalance()
|
||||||
override fun findInRegion(pointA: Vector3dc, pointB: Vector3dc) = kdTree.findInRegion(pointA, pointB)
|
override fun findInRegion(pointA: Vector3dc, pointB: Vector3dc) = kdTree.findInRegion(pointA, pointB)
|
||||||
|
override fun findInRange(origin: Vector3dc, range: Number) = kdTree.findInRange(origin, range)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ interface IDocument : EventDispatcher, INodeContainer {
|
||||||
fun findAt(vec: Vector3dc): Collection<INode<*>>
|
fun findAt(vec: Vector3dc): Collection<INode<*>>
|
||||||
fun rebalance()
|
fun rebalance()
|
||||||
fun findInRegion(pointA: Vector3dc, pointB: Vector3dc): Sequence<INode<*>>
|
fun findInRegion(pointA: Vector3dc, pointB: Vector3dc): Sequence<INode<*>>
|
||||||
|
fun findInRange(origin: Vector3dc, range: Number): Sequence<INode<*>>
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T : INode<T>> IDocument.createNode() = createNode(T::class)
|
inline fun <reified T : INode<T>> IDocument.createNode() = createNode(T::class)
|
||||||
|
|
|
@ -54,12 +54,20 @@ class KDTree(private val document: IDocument, private var root: Node = Node(Vect
|
||||||
find(translation)?.nodeIds?.remove(nodeId)
|
find(translation)?.nodeIds?.remove(nodeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findInRegion(pointA: Vector3dc, pointB: Vector3dc) = sequence<Long> {
|
fun findInRange(origin: Vector3dc, range: Number): Sequence<Node> {
|
||||||
|
val rangeD = range.toDouble()
|
||||||
|
val pointA = Vector3d(origin.x() - rangeD, origin.y() - rangeD, origin.z() - rangeD)
|
||||||
|
val pointB = Vector3d(origin.x() + rangeD, origin.y() + rangeD, origin.z() + rangeD)
|
||||||
|
|
||||||
|
return findInRegion(pointA, pointB).filter { it.vertex.distance(origin) <= rangeD }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findInRegion(pointA: Vector3dc, pointB: Vector3dc) = sequence<Node> {
|
||||||
var current: Node? = this@Node
|
var current: Node? = this@Node
|
||||||
val selection = mutableListOf<Node>()
|
val selection = mutableListOf<Node>()
|
||||||
while (current != null) {
|
while (current != null) {
|
||||||
if (pointA <= current.vertex && current.vertex <= pointB) {
|
if (pointA <= current.vertex && current.vertex <= pointB) {
|
||||||
yieldAll(current.nodeIds)
|
yield(current)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pointA[current.axis] < current.median) {
|
if (pointA[current.axis] < current.median) {
|
||||||
|
@ -143,8 +151,11 @@ class KDTree(private val document: IDocument, private var root: Node = Node(Vect
|
||||||
|
|
||||||
fun find(vertex: Vector3dc) = root.find(vertex)?.nodeIds?.mapNotNull(document::getNodeByNodeId) ?: emptyList()
|
fun find(vertex: Vector3dc) = root.find(vertex)?.nodeIds?.mapNotNull(document::getNodeByNodeId) ?: emptyList()
|
||||||
|
|
||||||
|
fun findInRange(origin: Vector3dc, range: Number) =
|
||||||
|
root.findInRange(origin, range).flatMap { it.nodeIds.asSequence() }.mapNotNull(document::getNodeByNodeId)
|
||||||
|
|
||||||
fun findInRegion(pointA: Vector3dc, pointB: Vector3dc) =
|
fun findInRegion(pointA: Vector3dc, pointB: Vector3dc) =
|
||||||
root.findInRegion(pointA, pointB).mapNotNull(document::getNodeByNodeId)
|
root.findInRegion(pointA, pointB).flatMap { it.nodeIds.asSequence() }.mapNotNull(document::getNodeByNodeId)
|
||||||
|
|
||||||
fun update(node: INode<*>) {
|
fun update(node: INode<*>) {
|
||||||
nodeLocMap[node.nodeId]?.let { root.remove(it, node.nodeId) }
|
nodeLocMap[node.nodeId]?.let { root.remove(it, node.nodeId) }
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package me.eater.test.threedom.dom
|
package me.eater.test.threedom.dom
|
||||||
|
|
||||||
import io.kotest.core.spec.style.StringSpec
|
import io.kotest.core.spec.style.StringSpec
|
||||||
import io.kotest.matchers.collections.*
|
import io.kotest.matchers.collections.shouldContainExactly
|
||||||
|
import io.kotest.matchers.collections.shouldHaveSingleElement
|
||||||
|
import io.kotest.matchers.collections.shouldHaveSize
|
||||||
import io.kotest.matchers.shouldBe
|
import io.kotest.matchers.shouldBe
|
||||||
import me.eater.threedom.dom.Document
|
import me.eater.threedom.dom.Document
|
||||||
import me.eater.threedom.dom.IDocument
|
import me.eater.threedom.dom.IDocument
|
||||||
|
@ -50,7 +52,7 @@ class PositionTest : StringSpec({
|
||||||
doc.findAt(-10, 40, 0) shouldHaveSingleElement nodeThree
|
doc.findAt(-10, 40, 0) shouldHaveSingleElement nodeThree
|
||||||
}
|
}
|
||||||
|
|
||||||
"ensure in selection works" {
|
"ensure in region works" {
|
||||||
val doc: IDocument = Document()
|
val doc: IDocument = Document()
|
||||||
val node = doc.createNode<PlainNode>()
|
val node = doc.createNode<PlainNode>()
|
||||||
val nodeTwo = doc.createNode<PlainNode>()
|
val nodeTwo = doc.createNode<PlainNode>()
|
||||||
|
@ -70,4 +72,25 @@ class PositionTest : StringSpec({
|
||||||
resultTwo shouldHaveSize 2
|
resultTwo shouldHaveSize 2
|
||||||
resultTwo shouldContainExactly listOf(nodeTwo, nodeThree)
|
resultTwo shouldContainExactly listOf(nodeTwo, nodeThree)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"ensure in range works" {
|
||||||
|
val doc: IDocument = Document()
|
||||||
|
val node = doc.createNode<PlainNode>()
|
||||||
|
val nodeTwo = doc.createNode<PlainNode>()
|
||||||
|
val nodeThree = doc.createNode<PlainNode>()
|
||||||
|
doc.addNode(node)
|
||||||
|
node.addNode(nodeTwo)
|
||||||
|
nodeTwo.addNode(nodeThree)
|
||||||
|
node.model { setTranslation(10, 0, 10) }
|
||||||
|
nodeTwo.model { setTranslation(-10, 20, 0) }
|
||||||
|
nodeThree.model { setTranslation(0, 20, 0) }
|
||||||
|
|
||||||
|
val result = doc.findInRange(Vector3d(0, 0, 0), 20).toList()
|
||||||
|
result shouldHaveSize 1
|
||||||
|
result shouldContainExactly listOf(node)
|
||||||
|
|
||||||
|
val resultTwo = doc.findInRange(Vector3d(0, 20, 10), 20).toList()
|
||||||
|
resultTwo shouldHaveSize 2
|
||||||
|
resultTwo shouldContainExactly listOf(nodeTwo, nodeThree)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue