commonMain.ru.casperix.math.axis_aligned.int32.Box3i.kt Maven / Gradle / Ivy
package ru.casperix.math.axis_aligned.int32
import ru.casperix.math.axis_aligned.Box
import ru.casperix.math.iteration.Box3Iterator
import ru.casperix.math.vector.int32.Vector3i
import kotlinx.serialization.Serializable
@Serializable
data class Box3i(override val min: Vector3i, override val max: Vector3i) : Box {
override val center = (max + min) / 2
override val dimension: Vector3i = Vector3i.ONE + max - min
override val volume: Int get() = dimension.x * dimension.y * dimension.z
fun grow(value: Int): Box3i {
return Box3i(min - Vector3i(value), max + Vector3i(value))
}
companion object {
fun createOrNull(min: Vector3i, max: Vector3i): Box3i? {
if (!(Vector3i.ONE + max - min).greaterOrEq(Vector3i.ZERO)) return null
return Box3i(min, max)
}
fun byRadius(center: Vector3i, radius: Vector3i): Box3i {
return Box3i(center - radius, center + radius)
}
fun byCorners(A: Vector3i, B: Vector3i): Box3i {
val min = A.lower(B)
val max = A.upper(B)
return Box3i(min, max)
}
fun byDimension(pos: Vector3i, size: Vector3i): Box3i {
return Box3i(pos, pos + size - Vector3i.ONE)
}
}
init {
if (!dimension.greaterOrEq(Vector3i.ZERO)) throw Error("Invalid box dimension $dimension");
}
override fun isInside(point: Vector3i): Boolean {
return point.greaterOrEq(min) && point.lessOrEq(max)
}
fun isSide(pos: Vector3i): Boolean {
return pos.x == min.x || pos.x == max.x || pos.y == min.y || pos.y == max.y || pos.z == min.z || pos.z == max.z
}
fun subdivide(): List? {
val next = (max + Vector3i.ONE - min) / 2
if (!min.less(next) || !next.less(max)) return null
val xRanges = arrayOf(Pair(min.x, next.x - 1), Pair(next.x, max.x))
val yRanges = arrayOf(Pair(min.y, next.y - 1), Pair(next.y, max.y))
val zRanges = arrayOf(Pair(min.z, next.z - 1), Pair(next.z, max.z))
val result = mutableListOf()
for (x in 0..1) {
for (y in 0..1) {
for (z in 0..1) {
val xRange = xRanges[x]
val yRange = yRanges[y]
val zRange = zRanges[z]
result.add(Box3i(Vector3i(xRange.first, yRange.first, zRange.first), Vector3i(xRange.second, yRange.second, zRange.second)))
}
}
}
return result
}
operator fun iterator(): Iterator {
return Box3Iterator(this)
}
override fun toString(): String {
return "AABBox3i(min=$min, max=$max)"
}
operator fun plus(offset: Vector3i): Box3i {
return Box3i(min + offset, max + offset)
}
fun intersection(other: Box3i): Box3i? {
val nextMin = min.upper(other.min)
val nextMax = max.lower(other.max)
if (nextMin.lessOrEq(nextMax)) {
return Box3i(nextMin, nextMax)
}
return null
}
}