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

it.unibo.alchemist.model.interfaces.geometry.Vector.kt Maven / Gradle / Ivy

There is a newer version: 20.0.1
Show newest version
package it.unibo.alchemist.model.interfaces.geometry

import kotlin.math.acos
import kotlin.math.sqrt

/**
 * A generic vector in a multidimensional space.
 *
 * @param S self type to prevent vector operations between vectors of different spaces.
 */
interface Vector> {

    /**
     * The dimensions of the space this vector belongs to.
     */
    val dimensions: Int

    /**
     * Coordinates for a Cartesian space.
     * Implementors must guarantee that internal state is not exposed.
     */
    val coordinates: DoubleArray

    /**
     * The coordinate of this vector in the specified dimension relatively to the basis
     * its space is described with.
     *
     * @param dim
     *            the dimension. E.g., in a 2-dimensional implementation, 0 could be the
     *            X-axis and 1 the Y-axis
     * @return the coordinate value
     */
    operator fun get(dim: Int): Double

    /**
     * Support for sum.
     * Note: the dimensions must coincide.
     * @return a vector containing the result
     */
    operator fun plus(other: S): S

    /**
     * Support for subtraction.
     * Note: the dimensions must coincide.
     * @return a vector containing the result
     */
    operator fun minus(other: S): S

    /**
     * Multiplication by a Double.
     * @return the resulting vector, the operation is not performed in-place.
     */
    operator fun times(other: Double): S

    /**
     * Division by a Double.
     * @return the resulting vector, the operation is not performed in-place.
     */
    @JvmDefault
    operator fun div(other: Double): S = times(1 / other)

    /**
     * Finds the magnitude of a vector.
     */
    @JvmDefault
    val magnitude get() = sqrt(coordinates.map { it * it }.sum())

    /**
     * Computes the dot product between two vectors.
     */
    @JvmDefault
    fun dot(other: S): Double = coordinates
        .zip(other.coordinates)
        .map { (a, b) -> a * b }
        .sum()

    /**
     * Computes the angle in radians between two vectors.
     */
    @JvmDefault
    fun angleBetween(other: S): Double = acos(dot(other) / (magnitude * other.magnitude))

    /**
     * Computes the distance between two vectors, interpreted as points in an Euclidean
     * space. Throws [IllegalArgumentException] if vectors have different dimensions.
     */
    fun distanceTo(other: S): Double

    /**
     * @return a resized version of the vector, whose magnitude is equal to [newLen].
     * Direction and verse of the original vector are preserved.
     */
    @JvmDefault
    fun resized(newLen: Double): S = normalized().times(newLen)

    /**
     * @return a normalized version of the vector (i.e. of unitary magnitude).
     */
    fun normalized(): S

    @Suppress("UNCHECKED_CAST")
    private fun resizedIf(toBeResized: Boolean, newLen: Double): S = when {
        toBeResized -> resized(newLen)
        else -> this as S
    }

    /**
     * @return this vector if its [magnitude] is smaller than or equal to [maximumMagnitude] or a resized version
     * of [maximumMagnitude] otherwise.
     */
    @JvmDefault
    fun coerceAtMost(maximumMagnitude: Double): S =
        resizedIf(magnitude > maximumMagnitude, maximumMagnitude)

    /**
     * @return this vector if its [magnitude] is greater than or equal to [minimumMagnitude] or a resized version
     * of [minimumMagnitude] otherwise.
     */
    @JvmDefault
    fun coerceAtLeast(minimumMagnitude: Double): S =
        resizedIf(magnitude < minimumMagnitude, minimumMagnitude)

    /**
     * Performs a coercion at least and at most.
     */
    @JvmDefault
    fun coerceIn(minimumMagnitude: Double, maximumMagnitude: Double): S =
        coerceAtLeast(minimumMagnitude).coerceAtMost(maximumMagnitude)

    /**
     * Find the normal of a vector.
     */
    fun normal(): S
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy