commonMain.utils.SweepQueue.kt Maven / Gradle / Ivy
The newest version!
package org.openrndr.kartifex.utils
import org.openrndr.collections.PriorityQueue
import kotlin.math.max
import kotlin.math.min
private fun copySign(magnitude: Double, sign: Double): Double {
return if (sign < 0.0) {
if (magnitude < 0.0) {
magnitude
} else {
-magnitude
}
} else {
if (magnitude > 0.0) {
magnitude
} else {
-magnitude
}
}
}
class SweepQueue {
class Event internal constructor(val key: Double, val value: T, val type: Int) {
companion object {
val COMPARATOR: Comparator> =
Comparator { a: Event<*>, b: Event<*> ->
val diff = a.key - b.key
if (diff == 0.0) {
a.type - b.type
} else {
copySign(1.0, diff).toInt()
}
}
}
}
@Suppress("UNCHECKED_CAST")
private val queue: PriorityQueue> = PriorityQueue(Event.COMPARATOR as Comparator>)
private val set = mutableSetOf()
fun add(value: T, a: Double, b: Double) {
queue.add(Event(min(a, b) - Scalars.EPSILON, value, OPEN))
queue.add(Event(max(a, b) + Scalars.EPSILON, value, CLOSED))
}
fun peek(): Double {
return if (queue.isEmpty()) Double.MAX_VALUE else queue.peek().key
}
operator fun next(): Event {
val e: Event = queue.poll() ?: error("queue empty")
if (e.type == CLOSED) {
set.remove(e.value)
} else {
set.add(e.value)
}
return e
}
fun take(): T? {
while (!queue.isEmpty()) {
val e = next()
if (e.type == OPEN) {
return e.value
}
}
return null
}
fun active(): Set {
return set
}
companion object {
const val OPEN = 0
const val CLOSED = 1
private fun compare(a: SweepQueue, b: SweepQueue): Int {
return Event.COMPARATOR.compare(a.queue.peek(), b.queue.peek())
}
fun next(vararg queues: SweepQueue): Int {
while (true) {
var minIdx = 0
for (i in 1 until queues.size) {
if (queues[minIdx].queue.isEmpty() || !queues[i].queue.isEmpty() && compare(
queues[i], queues[minIdx]
) < 0
) {
minIdx = i
}
}
val q = queues[minIdx]
if (q.queue.isEmpty() || q.queue.peek().type == OPEN) {
return minIdx
} else {
q.next()
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy