Compare commits

...

2 Commits

Author SHA1 Message Date
5129f29084 update geometry 2023-09-22 09:53:44 +03:00
7a4e9e70f9 add some quaternion operations 2023-09-22 08:21:14 +03:00
5 changed files with 46 additions and 41 deletions

View File

@ -77,4 +77,4 @@ ksciencePublish {
apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI") apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI")
val multikVersion by extra("0.2.0") val multikVersion by extra("0.2.2")

View File

@ -6,16 +6,26 @@
package space.kscience.kmath.geometry.euclidean2d package space.kscience.kmath.geometry.euclidean2d
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.kscience.kmath.geometry.Vector2D
import kotlin.math.PI import kotlin.math.PI
public interface Circle2D<T>{
public val center: Vector2D<T>
public val radius: Double
}
public val Circle2D<*>.circumference: Double get() = radius * 2 * PI
/** /**
* A circle in 2D space * A circle in 2D space
*/ */
@Serializable @Serializable
public data class Circle2D( public data class Float64Circle2D(
@Serializable(Float64Space2D.VectorSerializer::class) public val center: DoubleVector2D, @Serializable(Float64Space2D.VectorSerializer::class) override val center: Float64Vector2D,
public val radius: Double override val radius: Double
) ): Circle2D<Double>
public fun Circle2D(center: Float64Vector2D, radius: Double): Circle2D<Double> = Float64Circle2D(center, radius)
public val Circle2D.circumference: Double get() = radius * 2 * PI

View File

@ -22,9 +22,7 @@ import kotlin.math.sqrt
public interface Float32Vector2D : Vector2D<Float> public interface Float32Vector2D : Vector2D<Float>
public object Float32Space2D : public object Float32Space2D : GeometrySpace<Float32Vector2D>, ScaleOperations<Float32Vector2D> {
GeometrySpace<Float32Vector2D>,
ScaleOperations<Float32Vector2D> {
@Serializable @Serializable
@SerialName("Float32Vector2D") @SerialName("Float32Vector2D")

View File

@ -14,13 +14,11 @@ import kotlinx.serialization.encoding.Encoder
import space.kscience.kmath.geometry.GeometrySpace import space.kscience.kmath.geometry.GeometrySpace
import space.kscience.kmath.geometry.Vector2D import space.kscience.kmath.geometry.Vector2D
import space.kscience.kmath.operations.Float64Field import space.kscience.kmath.operations.Float64Field
import space.kscience.kmath.operations.Norm
import space.kscience.kmath.operations.ScaleOperations import space.kscience.kmath.operations.ScaleOperations
import kotlin.math.pow import kotlin.math.pow
import kotlin.math.sqrt import kotlin.math.sqrt
public typealias DoubleVector2D = Vector2D<Double> public typealias DoubleVector2D = Vector2D<Double>
public typealias Float64Vector2D = Vector2D<Double> public typealias Float64Vector2D = Vector2D<Double>
@ -30,9 +28,7 @@ public val Vector2D<Double>.r: Double get() = Float64Space2D.norm(this)
/** /**
* 2D Euclidean space * 2D Euclidean space
*/ */
public object Float64Space2D : GeometrySpace<DoubleVector2D>, public object Float64Space2D : GeometrySpace<DoubleVector2D>, ScaleOperations<DoubleVector2D> {
ScaleOperations<DoubleVector2D>,
Norm<DoubleVector2D, Double> {
@Serializable @Serializable
@SerialName("Float64Vector2D") @SerialName("Float64Vector2D")
@ -72,4 +68,6 @@ public object Float64Space2D : GeometrySpace<DoubleVector2D>,
public val yAxis: DoubleVector2D = vector(0.0, 1.0) public val yAxis: DoubleVector2D = vector(0.0, 1.0)
} }
public fun Float64Vector2D(x: Number, y: Number): Float64Vector2D = Float64Space2D.vector(x, y)
public val Float64Field.euclidean2D: Float64Space2D get() = Float64Space2D public val Float64Field.euclidean2D: Float64Space2D get() = Float64Space2D

View File

@ -8,13 +8,7 @@ package space.kscience.kmath.geometry
import space.kscience.kmath.complex.Quaternion import space.kscience.kmath.complex.Quaternion
import space.kscience.kmath.complex.QuaternionAlgebra import space.kscience.kmath.complex.QuaternionAlgebra
import space.kscience.kmath.complex.conjugate import space.kscience.kmath.complex.conjugate
import space.kscience.kmath.complex.normalized
import space.kscience.kmath.geometry.euclidean3d.Float32Space3D
import space.kscience.kmath.geometry.euclidean3d.Float32Vector3D
import space.kscience.kmath.geometry.euclidean3d.theta import space.kscience.kmath.geometry.euclidean3d.theta
import kotlin.math.asin
import kotlin.math.atan2
import kotlin.math.pow
public operator fun Quaternion.times(other: Quaternion): Quaternion = QuaternionAlgebra.multiply(this, other) public operator fun Quaternion.times(other: Quaternion): Quaternion = QuaternionAlgebra.multiply(this, other)
@ -28,28 +22,33 @@ public fun Quaternion.power(number: Number): Quaternion = QuaternionAlgebra.powe
public fun QuaternionAlgebra.slerp(from: Quaternion, to: Quaternion, fraction: Double): Quaternion = public fun QuaternionAlgebra.slerp(from: Quaternion, to: Quaternion, fraction: Double): Quaternion =
(to / from).pow(fraction) * from (to / from).pow(fraction) * from
/**
* Scalar angle between two quaternions
*/
public fun QuaternionAlgebra.angleBetween(q1: Quaternion, q2: Quaternion): Angle = (q1.conjugate * q2).theta public fun QuaternionAlgebra.angleBetween(q1: Quaternion, q2: Quaternion): Angle = (q1.conjugate * q2).theta
public val Quaternion.inclination: Radians get() = asin(2 * (w * y - x * z)).radians /**
* Euclidean product of two quaternions
public val Quaternion.azimuth: Angle get() = atan2(2 * (w * z + x * y), 1 - 2 * (y.pow(2) + z.pow(2))).radians.normalized() */
public infix fun Quaternion.dot(other: Quaternion): Double = w * other.w + x * other.x + y * other.y + z * other.z public infix fun Quaternion.dot(other: Quaternion): Double = w * other.w + x * other.x + y * other.y + z * other.z
//
///**
// * Convert a quaternion to XYZ Cardan angles assuming it is normalized.
// */
//private fun Quaternion.normalizedToEuler(): Float32Vector3D {
// val roll = atan2(2 * y * w + 2 * x * z, 1 - 2 * y * y - 2 * z * z)
// val pitch = atan2(2 * x * w - 2 * y * z, 1 - 2 * x * x - 2 * z * z)
// val yaw = asin(2 * x * y + 2 * z * w)
//
// return Float32Vector3D(roll, pitch, yaw)
//}
private fun Quaternion.normalizedToEuler(): Float32Vector3D { ///**
val roll = atan2(2 * y * w + 2 * x * z, 1 - 2 * y * y - 2 * z * z); // * Quaternion to XYZ Cardan angles
val pitch = atan2(2 * x * w - 2 * y * z, 1 - 2 * x * x - 2 * z * z); // */
val yaw = asin(2 * x * y + 2 * z * w); //public fun Quaternion.toEuler(): Float32Vector3D = if (QuaternionAlgebra.norm(this) == 0.0) {
// Float32Space3D.zero
return Float32Vector3D(roll, pitch, yaw) //} else {
} // normalized().normalizedToEuler()
//}
/**
* Quaternion to XYZ Cardan angles
*/
public fun Quaternion.toEuler(): Float32Vector3D = if (QuaternionAlgebra.norm(this) == 0.0) {
Float32Space3D.zero
} else {
normalized().normalizedToEuler()
}