All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.math.quad_matrix.float64.Matrix3d.kt Maven / Gradle / Ivy

package ru.casperix.math.quad_matrix.float64

import ru.casperix.math.quad_matrix.QuadMatrix
import ru.casperix.math.quad_matrix.QuadMatrixBuilder
import ru.casperix.math.quad_matrix.float32.Matrix3f
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.math.vector.float64.Vector2d
import ru.casperix.math.vector.float64.Vector3d
import ru.casperix.misc.toFloatArray
import kotlinx.serialization.Serializable
import kotlin.math.cos
import kotlin.math.sin

@Serializable
data class Matrix3d(val data: DoubleArray) : QuadMatrix {
//	constructor(vararg data: Double) : this(doubleArrayOf(*data))

    init {
        if (data.size != 9) throw Error("Source expected 9 elements, but actual ${data.size}")
    }

    operator fun get(x: Int, y: Int): Double {
        return data[x + y * 3]
    }

    operator fun get(index: Int): Double {
        return data[index]
    }


    override operator fun times(other: Matrix3d): Matrix3d {
        val A = data
        val B = other.data


        return Matrix3d(
            doubleArrayOf(
                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 toMatrix3f(): Matrix3f {
        return Matrix3f(data.toFloatArray())
    }

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other == null || this::class != other::class) return false

        other as Matrix3d

        if (!data.contentEquals(other.data)) return false

        return true
    }

    override fun hashCode(): Int {
        return data.hashCode()
    }

    override fun transpose(): Matrix3d {
        return Matrix3d(
            doubleArrayOf(
                data[i00], data[i01], data[i02],
                data[i10], data[i11], data[i12],
                data[i20], data[i21], data[i22],
            )
        )
    }

    override fun determinant(): Double {
        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(): Matrix3d {
        val det = determinant()
        if (det == 0.0) throw Error("Can't invert a singular matrix")
        val invDet = 1.0 / det

        return Matrix3d(
            doubleArrayOf(
                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: Vector2d): Vector2d {
        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 Vector2d(rx * rw, ry * rw)
    }

    fun transform(value: Vector3d): Vector3d {
        return Vector3d(
            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,
        )
    }

    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


        override fun translate(value: Vector2d): Matrix3d {
            return Matrix3d(
                doubleArrayOf(
                    1.0, 0.0, 0.0,
                    0.0, 1.0, 0.0,
                    value.x, value.y, 1.0
                )
            )
        }

        override fun rotate(value: Double): Matrix3d {
            val cos = cos(value)
            val sin = sin(value)
            return Matrix3d(
                doubleArrayOf(
                    cos, -sin, 0.0,
                    sin, cos, 0.0,
                    0.0, 0.0, 1.0
                )
            )
        }

        override fun scale(value: Vector2d): Matrix3d {
            return Matrix3d(
                doubleArrayOf(
                    value.x, 0.0, 0.0,
                    0.0, value.y, 0.0,
                    0.0, 0.0, 1.0
                )
            )
        }


        fun byIndex(factory: (Int) -> Double): Matrix3d {
            return Matrix3d(DoubleArray(9) { factory(it) })
        }

        @Deprecated(message = "use Matrix3f(floatArrayOf())")
        fun fromValues(vararg values: Double): Matrix3d {
            return byIndex { values.getOrNull(it) ?: 0.0 }
        }

        val IDENTITY = byIndex { if (it % 4 == 0) 1.0 else 0.0 }


        fun scale(value: Vector3d): Matrix3d {
            return fromValues(
                value.x, 0.0, 0.0,
                0.0, value.y, 0.0,
                0.0, 0.0, value.z,
            )
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy