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")
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
import kotlinx.serialization.Serializable
import space.kscience.kmath.geometry.Vector2D
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
*/
@Serializable
public data class Circle2D(
@Serializable(Float64Space2D.VectorSerializer::class) public val center: DoubleVector2D,
public val radius: Double
)
public data class Float64Circle2D(
@Serializable(Float64Space2D.VectorSerializer::class) override val center: Float64Vector2D,
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

@ -19,12 +19,10 @@ import kotlin.math.pow
import kotlin.math.sqrt
@Serializable(Float32Space2D.VectorSerializer::class)
public interface Float32Vector2D: Vector2D<Float>
public interface Float32Vector2D : Vector2D<Float>
public object Float32Space2D :
GeometrySpace<Float32Vector2D>,
ScaleOperations<Float32Vector2D> {
public object Float32Space2D : GeometrySpace<Float32Vector2D>, ScaleOperations<Float32Vector2D> {
@Serializable
@SerialName("Float32Vector2D")

View File

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

View File

@ -8,13 +8,7 @@ package space.kscience.kmath.geometry
import space.kscience.kmath.complex.Quaternion
import space.kscience.kmath.complex.QuaternionAlgebra
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 kotlin.math.asin
import kotlin.math.atan2
import kotlin.math.pow
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 =
(to / from).pow(fraction) * from
/**
* Scalar angle between two quaternions
*/
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
public val Quaternion.azimuth: Angle get() = atan2(2 * (w * z + x * y), 1 - 2 * (y.pow(2) + z.pow(2))).radians.normalized()
/**
* Euclidean product of two quaternions
*/
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);
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)
}
/**
* Quaternion to XYZ Cardan angles
*/
public fun Quaternion.toEuler(): Float32Vector3D = if (QuaternionAlgebra.norm(this) == 0.0) {
Float32Space3D.zero
} else {
normalized().normalizedToEuler()
}
///**
// * Quaternion to XYZ Cardan angles
// */
//public fun Quaternion.toEuler(): Float32Vector3D = if (QuaternionAlgebra.norm(this) == 0.0) {
// Float32Space3D.zero
//} else {
// normalized().normalizedToEuler()
//}