[orx-kdtree] Add support for range query in kd-tree (#201)
This commit is contained in:
39
orx-kdtree/src/demo/kotlin/DemoRangeQuery01.kt
Normal file
39
orx-kdtree/src/demo/kotlin/DemoRangeQuery01.kt
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.kdtree.buildKDTree
|
||||||
|
import org.openrndr.extra.kdtree.findAllInRange
|
||||||
|
import org.openrndr.extra.kdtree.vector2Mapper
|
||||||
|
import org.openrndr.math.Vector2
|
||||||
|
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
application {
|
||||||
|
|
||||||
|
configure {
|
||||||
|
width = 1080
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
|
||||||
|
program {
|
||||||
|
val points = MutableList(1000) {
|
||||||
|
Vector2(Math.random() * width, Math.random() * height)
|
||||||
|
}
|
||||||
|
val tree = buildKDTree(points, 2, ::vector2Mapper)
|
||||||
|
val radius = 50.0
|
||||||
|
|
||||||
|
extend {
|
||||||
|
drawer.circles(points, 5.0)
|
||||||
|
|
||||||
|
val allInRange = findAllInRange(tree, mouse.position, maxDistance = radius, dimensions = 2, ::vector2Mapper)
|
||||||
|
drawer.fill = ColorRGBa.PINK
|
||||||
|
drawer.stroke = ColorRGBa.PINK
|
||||||
|
drawer.strokeWeight = 2.0
|
||||||
|
drawer.circles(allInRange, 7.0)
|
||||||
|
|
||||||
|
drawer.fill = null
|
||||||
|
drawer.strokeWeight = 1.0
|
||||||
|
drawer.circle(mouse.position, radius)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -268,6 +268,47 @@ fun <T> findNearest(root: KDTreeNode<T>, item: T, dimensions: Int, mapper: (T, I
|
|||||||
return nearestArg?.item
|
return nearestArg?.item
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> findAllInRange(
|
||||||
|
root: KDTreeNode<T>,
|
||||||
|
item: T,
|
||||||
|
maxDistance: Double,
|
||||||
|
dimensions: Int,
|
||||||
|
mapper: (T, Int) -> Double
|
||||||
|
) : List<T> {
|
||||||
|
|
||||||
|
val sqrMaxDist = maxDistance * maxDistance
|
||||||
|
val queue = kotlin.collections.ArrayDeque<KDTreeNode<T>?>()
|
||||||
|
queue.add(root)
|
||||||
|
val results = mutableListOf<T?>()
|
||||||
|
|
||||||
|
while (queue.isNotEmpty()) {
|
||||||
|
val node = queue.removeFirst()
|
||||||
|
if (node != null) {
|
||||||
|
val dimensionValue = mapper(item, node.dimension)
|
||||||
|
val distance = sqrDistance(item, node.item
|
||||||
|
?: throw IllegalStateException("item is null"), dimensions, mapper)
|
||||||
|
if (distance <= sqrMaxDist) {
|
||||||
|
results.add(node.item)
|
||||||
|
}
|
||||||
|
|
||||||
|
val route: Int = if (dimensionValue < node.median) {
|
||||||
|
queue.add(node.children[0])
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
queue.add(node.children[1])
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
val d = abs(node.median - dimensionValue)
|
||||||
|
if (d * d <= sqrMaxDist) {
|
||||||
|
queue.add(node.children[1 - route])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results.filterNotNull()
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> insert(root: KDTreeNode<T>, item: T, dimensions: Int, mapper: (T, Int) -> Double): KDTreeNode<T> {
|
fun <T> insert(root: KDTreeNode<T>, item: T, dimensions: Int, mapper: (T, Int) -> Double): KDTreeNode<T> {
|
||||||
val stack = Stack<KDTreeNode<T>>()
|
val stack = Stack<KDTreeNode<T>>()
|
||||||
stack.push(root)
|
stack.push(root)
|
||||||
|
|||||||
Reference in New Issue
Block a user