
commonMain.ru.casperix.math.quad_matrix.float32.Matrix3f.kt Maven / Gradle / Ivy
package ru.casperix.math.quad_matrix.float32
import kotlinx.serialization.Serializable
import ru.casperix.math.angle.float32.DegreeFloat
import ru.casperix.math.angle.float32.RadianFloat
import ru.casperix.math.axis_aligned.float32.Dimension2f
import ru.casperix.math.axis_aligned.int32.Dimension2i
import ru.casperix.math.geometry.Polygon2f
import ru.casperix.math.geometry.Quad2f
import ru.casperix.math.geometry.Triangle2f
import ru.casperix.math.geometry.fDEGREE_TO_RADIAN
import ru.casperix.math.quad_matrix.QuadMatrix
import ru.casperix.math.quad_matrix.QuadMatrixBuilder
import ru.casperix.math.quad_matrix.float64.Matrix3d
import ru.casperix.math.straight_line.float32.LineSegment2f
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.math.vector.float32.Vector3f
import ru.casperix.misc.toDoubleArray
import kotlin.math.cos
import kotlin.math.sin
@Serializable
data class Matrix3f(val data: FloatArray) : QuadMatrix {
// constructor(vararg data: Float) : this(floatArrayOf(*data))
init {
if (data.size != 9) throw Error("Source expected 9 elements, but actual ${data.size}")
}
operator fun get(x: Int, y: Int): Float {
return data[x + y * 3]
}
operator fun get(index: Int): Float {
return data[index]
}
override operator fun times(other: Matrix3f): Matrix3f {
if (this === IDENTITY) return other
if (other === IDENTITY) return this
val A = data
val B = other.data
return Matrix3f(
floatArrayOf(
A[i00] * B[i00] + A[i10] * B[i01] + A[i20] * B[i02],
A[i00] * B[i10] + A[i10] * B[i11] + A[i20] * B[i12],
A[i00] * B[i20] + A[i10] * B[i21] + A[i20] * B[i22],
A[i01] * B[i00] + A[i11] * B[i01] + A[i21] * B[i02],
A[i01] * B[i10] + A[i11] * B[i11] + A[i21] * B[i12],
A[i01] * B[i20] + A[i11] * B[i21] + A[i21] * B[i22],
A[i02] * B[i00] + A[i12] * B[i01] + A[i22] * B[i02],
A[i02] * B[i10] + A[i12] * B[i11] + A[i22] * B[i12],
A[i02] * B[i20] + A[i12] * B[i21] + A[i22] * B[i22],
)
)
}
fun toMatrix3d(): Matrix3d {
return Matrix3d(data.toDoubleArray())
}
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || this::class != other::class) return false
other as Matrix3f
if (!data.contentEquals(other.data)) return false
return true
}
override fun hashCode(): Int {
return data.hashCode()
}
override fun transpose(): Matrix3f {
return Matrix3f(
floatArrayOf(
data[i00], data[i01], data[i02],
data[i10], data[i11], data[i12],
data[i20], data[i21], data[i22],
)
)
}
override fun determinant(): Float {
return data[0] * data[4] * data[8] + data[3] * data[7] * data[2] + data[6] * data[1] * data[5] - (data[0] * data[7] * data[5]) - data[3] * data[1] * data[8] - data[6] * data[4] * data[2]
}
override fun inverse(): Matrix3f {
val det: Float = determinant()
if (det == 0f) throw Error("Can't invert a singular matrix")
val invDet = 1.0f / det
return Matrix3f(
floatArrayOf(
invDet * (data[4] * data[8] - data[5] * data[7]),
invDet * (data[2] * data[7] - data[1] * data[8]),
invDet * (data[1] * data[5] - data[2] * data[4]),
invDet * (data[5] * data[6] - data[3] * data[8]),
invDet * (data[0] * data[8] - data[2] * data[6]),
invDet * (data[2] * data[3] - data[0] * data[5]),
invDet * (data[3] * data[7] - data[4] * data[6]),
invDet * (data[1] * data[6] - data[0] * data[7]),
invDet * (data[0] * data[4] - data[1] * data[3]),
)
)
}
fun transform(value: LineSegment2f): LineSegment2f {
return LineSegment2f(transform(value.start), transform(value.finish))
}
fun transform(value: Vector2f): Vector2f {
val rx = value.x * data[0] + value.y * data[3] + data[6]
val ry = value.x * data[1] + value.y * data[4] + data[7]
val rw = 1 / (value.x * data[2] + value.y * data[5] + data[8])
return Vector2f(rx * rw, ry * rw)
}
fun transform(value: Vector3f): Vector3f {
return Vector3f(
data[0] * value.x + data[1] * value.y + data[2] * value.z,
data[3] * value.x + data[4] * value.y + data[5] * value.z,
data[6] * value.x + data[7] * value.y + data[8] * value.z,
)
}
fun transform(quad: Quad2f): Quad2f {
if (this == IDENTITY) return quad
return quad.convert { transform(it) }
}
fun transform(triangle: Triangle2f): Triangle2f {
if (this == IDENTITY) return triangle
return triangle.convert { transform(it) }
}
fun transform(quad: Polygon2f): Polygon2f {
if (this == IDENTITY) return quad
return quad.convert { transform(it) }
}
fun getTranslate(): Vector2f {
return Vector2f(data[6], data[7])
}
companion object : QuadMatrixBuilder {
private val i00 = 0
private val i10 = 1
private val i20 = 2
private val i01 = 3
private val i11 = 4
private val i21 = 5
private val i02 = 6
private val i12 = 7
private val i22 = 8
fun mul(A: Matrix3f, B: Matrix3f): Matrix3f {
return A * B
}
fun compose(scale: Vector2f = Vector2f.ONE, degree: DegreeFloat = DegreeFloat.ZERO, translate: Vector2f = Vector2f.ZERO): Matrix3f =
scale(scale) * rotate(degree) * translate(translate)
fun compose(scale: Vector2f = Vector2f.ONE, radian: RadianFloat = RadianFloat.ZERO, translate: Vector2f = Vector2f.ZERO): Matrix3f =
scale(scale) * rotate(radian) * translate(translate)
fun orthographic(dimension: Dimension2i, yDown: Boolean): Matrix3f {
return orthographic(dimension.toDimension2f(), yDown)
}
fun orthographic(dimension: Dimension2f, yDown: Boolean): Matrix3f {
return if (yDown) {
orthographic(
0f,
dimension.width.toFloat(),
dimension.height.toFloat(),
0f,
)
} else {
orthographic(
0f,
dimension.width.toFloat(),
0f,
dimension.height.toFloat(),
)
}
}
fun orthographic(left: Float, right: Float, bottom: Float, top: Float): Matrix3f {
val tx = -(right + left) / (right - left)
val ty = -(top + bottom) / (top - bottom)
return Matrix3f(
floatArrayOf(
2f / (right - left), 0f, 0f,
0f, 2f / (top - bottom), 0f,
tx, ty, 1f,
)
)
}
override fun translate(value: Vector2f) = Matrix3f(
floatArrayOf(
1f, 0f, 0f,
0f, 1f, 0f,
value.x, value.y, 1f
)
)
override fun rotate(angle: RadianFloat) = rotateRadian(angle.value)
fun rotateRadian(value: Float): Matrix3f {
val cos = cos(value)
val sin = sin(value)
return Matrix3f(
floatArrayOf(
cos, -sin, 0f,
sin, cos, 0f,
0f, 0f, 1f
)
)
}
override fun scale(value: Vector2f): Matrix3f {
return Matrix3f(
floatArrayOf(
value.x, 0f, 0f,
0f, value.y, 0f,
0f, 0f, 1f
)
)
}
fun translate(x: Float, y: Float): Matrix3f = translate(Vector2f(x, y))
fun rotate(angle: DegreeFloat): Matrix3f = rotate(angle.toRadian())
fun rotateDegree(angle: Float): Matrix3f = rotateRadian(angle * fDEGREE_TO_RADIAN)
fun scale(x: Float, y: Float): Matrix3f = scale(Vector2f(x, y))
fun byIndex(factory: (Int) -> Float): Matrix3f {
return Matrix3f(FloatArray(9) { factory(it) })
}
@Deprecated(message = "use Matrix3f(floatArrayOf())")
fun fromValues(vararg values: Float): Matrix3f {
return byIndex { values.getOrNull(it) ?: 0f }
}
val IDENTITY = byIndex { if (it % 4 == 0) 1f else 0f }
fun scale(value: Vector3f) = Matrix3f(
floatArrayOf(
value.x, 0f, 0f,
0f, value.y, 0f,
0f, 0f, value.z,
)
)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy