[WIP] geometry refactor
This commit is contained in:
parent
5965ca940b
commit
875e32679b
@ -26,6 +26,7 @@
|
|||||||
- Algebra now has an obligatory `bufferFactory` (#477).
|
- Algebra now has an obligatory `bufferFactory` (#477).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- Removed marker `Vector` type for geometry
|
||||||
- Geometry uses type-safe angles
|
- Geometry uses type-safe angles
|
||||||
- Tensor operations switched to prefix notation
|
- Tensor operations switched to prefix notation
|
||||||
- Row-wise and column-wise ND shapes in the core
|
- Row-wise and column-wise ND shapes in the core
|
||||||
|
@ -15,7 +15,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.3.1-dev-RC"
|
version = "0.3.2-dev-"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
@ -66,10 +66,10 @@ ksciencePublish {
|
|||||||
}
|
}
|
||||||
github("kmath", "SciProgCentre")
|
github("kmath", "SciProgCentre")
|
||||||
space(
|
space(
|
||||||
if (isInDevelopment) {
|
if (findProperty("production") == "true" || !isInDevelopment) {
|
||||||
"https://maven.pkg.jetbrains.space/spc/p/sci/dev"
|
|
||||||
} else {
|
|
||||||
"https://maven.pkg.jetbrains.space/spc/p/sci/maven"
|
"https://maven.pkg.jetbrains.space/spc/p/sci/maven"
|
||||||
|
} else {
|
||||||
|
"https://maven.pkg.jetbrains.space/spc/p/sci/dev"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
sonatype()
|
sonatype()
|
||||||
|
@ -6,8 +6,10 @@
|
|||||||
package space.kscience.kmath.geometry
|
package space.kscience.kmath.geometry
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo
|
import kotlin.math.PI
|
||||||
import kotlin.math.*
|
|
||||||
|
interface Circle<T>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A circle in 2D space
|
* A circle in 2D space
|
||||||
|
@ -17,7 +17,7 @@ import space.kscience.kmath.operations.ScaleOperations
|
|||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
public interface Vector2D<T> : Point<T>, Vector {
|
public interface Vector2D<T> : Point<T> {
|
||||||
public val x: T
|
public val x: T
|
||||||
public val y: T
|
public val y: T
|
||||||
override val size: Int get() = 2
|
override val size: Int get() = 2
|
||||||
@ -47,7 +47,8 @@ public val Vector2D<Double>.r: Double get() = Euclidean2DSpace.norm(this)
|
|||||||
/**
|
/**
|
||||||
* 2D Euclidean space
|
* 2D Euclidean space
|
||||||
*/
|
*/
|
||||||
public object Euclidean2DSpace : GeometrySpace<DoubleVector2D>,
|
public object Euclidean2DSpace :
|
||||||
|
GeometrySpace<DoubleVector2D, Double>,
|
||||||
ScaleOperations<DoubleVector2D>,
|
ScaleOperations<DoubleVector2D>,
|
||||||
Norm<DoubleVector2D, Double> {
|
Norm<DoubleVector2D, Double> {
|
||||||
|
|
||||||
@ -87,4 +88,6 @@ public object Euclidean2DSpace : GeometrySpace<DoubleVector2D>,
|
|||||||
|
|
||||||
public val xAxis: DoubleVector2D = vector(1.0, 0.0)
|
public val xAxis: DoubleVector2D = vector(1.0, 0.0)
|
||||||
public val yAxis: DoubleVector2D = vector(0.0, 1.0)
|
public val yAxis: DoubleVector2D = vector(0.0, 1.0)
|
||||||
|
|
||||||
|
override val defaultPrecision: Double = 1e-6
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import space.kscience.kmath.structures.Buffer
|
|||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
public interface Vector3D<T> : Point<T>, Vector {
|
public interface Vector3D<T> : Point<T> {
|
||||||
public val x: T
|
public val x: T
|
||||||
public val y: T
|
public val y: T
|
||||||
public val z: T
|
public val z: T
|
||||||
@ -55,7 +55,7 @@ public typealias Float64Vector3D = Vector3D<Double>
|
|||||||
|
|
||||||
public val DoubleVector3D.r: Double get() = Euclidean3DSpace.norm(this)
|
public val DoubleVector3D.r: Double get() = Euclidean3DSpace.norm(this)
|
||||||
|
|
||||||
public object Euclidean3DSpace : GeometrySpace<DoubleVector3D>, ScaleOperations<DoubleVector3D>,
|
public object Euclidean3DSpace : GeometrySpace<DoubleVector3D, Double>, ScaleOperations<DoubleVector3D>,
|
||||||
Norm<DoubleVector3D, Double> {
|
Norm<DoubleVector3D, Double> {
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -146,4 +146,6 @@ public object Euclidean3DSpace : GeometrySpace<DoubleVector3D>, ScaleOperations<
|
|||||||
public val xAxis: DoubleVector3D = vector(1.0, 0.0, 0.0)
|
public val xAxis: DoubleVector3D = vector(1.0, 0.0, 0.0)
|
||||||
public val yAxis: DoubleVector3D = vector(0.0, 1.0, 0.0)
|
public val yAxis: DoubleVector3D = vector(0.0, 1.0, 0.0)
|
||||||
public val zAxis: DoubleVector3D = vector(0.0, 0.0, 1.0)
|
public val zAxis: DoubleVector3D = vector(0.0, 0.0, 1.0)
|
||||||
|
|
||||||
|
override val defaultPrecision: Double = 1e-6
|
||||||
}
|
}
|
||||||
|
@ -9,23 +9,26 @@ import space.kscience.kmath.operations.Group
|
|||||||
import space.kscience.kmath.operations.Norm
|
import space.kscience.kmath.operations.Norm
|
||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
|
|
||||||
public interface Vector
|
/**
|
||||||
|
* A geometry vector space
|
||||||
public interface GeometrySpace<V : Vector> : Group<V>, ScaleOperations<V>, Norm<V, Double> {
|
* @param V the type of vector object
|
||||||
|
* @param D the type of distance
|
||||||
|
*/
|
||||||
|
public interface GeometrySpace<V : Any, D: Comparable<D>> : Group<V>, ScaleOperations<V>, Norm<V, D> {
|
||||||
/**
|
/**
|
||||||
* L2 distance
|
* L2 distance
|
||||||
*/
|
*/
|
||||||
public fun V.distanceTo(other: V): Double
|
public fun V.distanceTo(other: V): D
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scalar product
|
* Scalar product
|
||||||
*/
|
*/
|
||||||
public infix fun V.dot(other: V): Double
|
public infix fun V.dot(other: V): Double
|
||||||
|
|
||||||
public companion object{
|
|
||||||
/**
|
/**
|
||||||
* Default precision for geometry objects comparison
|
* Default precision for geometry objects comparison
|
||||||
*/
|
*/
|
||||||
internal const val DEFAULT_PRECISION = 1e-6
|
public val defaultPrecision: D
|
||||||
}
|
|
||||||
|
public companion object
|
||||||
}
|
}
|
@ -12,16 +12,16 @@ import kotlinx.serialization.Serializable
|
|||||||
* A line formed by [start] vector of start and a [direction] vector. Direction vector is not necessarily normalized,
|
* A line formed by [start] vector of start and a [direction] vector. Direction vector is not necessarily normalized,
|
||||||
* but its length does not affect line properties
|
* but its length does not affect line properties
|
||||||
*/
|
*/
|
||||||
public interface Line<out V : Vector> {
|
public interface Line<out V : Any> {
|
||||||
public val start: V
|
public val start: V
|
||||||
public val direction: V
|
public val direction: V
|
||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("Line")
|
@SerialName("Line")
|
||||||
private data class LineImpl<out V : Vector>(override val start: V, override val direction: V): Line<V>
|
private data class LineImpl<out V : Any>(override val start: V, override val direction: V) : Line<V>
|
||||||
|
|
||||||
public fun <V : Vector> Line(base: V, direction: V): Line<V> = LineImpl(base, direction)
|
public fun <V : Any> Line(base: V, direction: V): Line<V> = LineImpl(base, direction)
|
||||||
|
|
||||||
public typealias Line2D = Line<DoubleVector2D>
|
public typealias Line2D = Line<DoubleVector2D>
|
||||||
public typealias Line3D = Line<DoubleVector3D>
|
public typealias Line3D = Line<DoubleVector3D>
|
||||||
@ -29,7 +29,7 @@ public typealias Line3D = Line<DoubleVector3D>
|
|||||||
/**
|
/**
|
||||||
* A directed line segment between [begin] and [end]
|
* A directed line segment between [begin] and [end]
|
||||||
*/
|
*/
|
||||||
public interface LineSegment<out V : Vector> {
|
public interface LineSegment<out V : Any> {
|
||||||
public val begin: V
|
public val begin: V
|
||||||
public val end: V
|
public val end: V
|
||||||
}
|
}
|
||||||
@ -39,11 +39,11 @@ public interface LineSegment<out V : Vector> {
|
|||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
@SerialName("LineSegment")
|
@SerialName("LineSegment")
|
||||||
private data class LineSegmentImpl<out V : Vector>(override val begin: V, override val end: V) : LineSegment<V>
|
private data class LineSegmentImpl<out V : Any>(override val begin: V, override val end: V) : LineSegment<V>
|
||||||
|
|
||||||
public fun <V : Vector> LineSegment(begin: V, end: V): LineSegment<V> = LineSegmentImpl(begin, end)
|
public fun <V : Any> LineSegment(begin: V, end: V): LineSegment<V> = LineSegmentImpl(begin, end)
|
||||||
|
|
||||||
public fun <V : Vector> LineSegment<V>.line(algebra: GeometrySpace<V>): Line<V> = with(algebra) {
|
public fun <V : Any> LineSegment<V>.line(algebra: GeometrySpace<V, *>): Line<V> = with(algebra) {
|
||||||
Line(begin, end - begin)
|
Line(begin, end - begin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ package space.kscience.kmath.geometry
|
|||||||
* @param vector to project
|
* @param vector to project
|
||||||
* @param line line to which vector should be projected
|
* @param line line to which vector should be projected
|
||||||
*/
|
*/
|
||||||
public fun <V : Vector> GeometrySpace<V>.projectToLine(vector: V, line: Line<V>): V = with(line) {
|
public fun <V : Any> GeometrySpace<V, *>.projectToLine(vector: V, line: Line<V>): V = with(line) {
|
||||||
start + (direction dot (vector - start)) / (direction dot direction) * direction
|
start + (direction dot (vector - start)) / (direction dot direction) * direction
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,5 +23,5 @@ public fun <V : Vector> GeometrySpace<V>.projectToLine(vector: V, line: Line<V>)
|
|||||||
* @param normal normal (perpendicular) vector to a hyper-plane to which vector should be projected
|
* @param normal normal (perpendicular) vector to a hyper-plane to which vector should be projected
|
||||||
* @param base point belonging to a hyper-plane to which vector should be projected
|
* @param base point belonging to a hyper-plane to which vector should be projected
|
||||||
*/
|
*/
|
||||||
public fun <V : Vector> GeometrySpace<V>.projectAlong(vector: V, normal: V, base: V): V =
|
public fun <V : Any> GeometrySpace<V, *>.projectAlong(vector: V, normal: V, base: V): V =
|
||||||
vector + normal * ((base - vector) dot normal) / (normal dot normal)
|
vector + normal * ((base - vector) dot normal) / (normal dot normal)
|
||||||
|
@ -5,27 +5,14 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.geometry
|
package space.kscience.kmath.geometry
|
||||||
|
|
||||||
import space.kscience.kmath.geometry.GeometrySpace.Companion.DEFAULT_PRECISION
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Float equality within given [precision]
|
|
||||||
*/
|
|
||||||
public fun Double.equalsFloat(other: Double, precision: Double = DEFAULT_PRECISION): Boolean =
|
|
||||||
kotlin.math.abs(this - other) < precision
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Float equality within given [precision]
|
|
||||||
*/
|
|
||||||
public fun Double.equalsFloat(other: Float, precision: Double = DEFAULT_PRECISION): Boolean =
|
|
||||||
kotlin.math.abs(this - other) < precision
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vector equality within given [precision] (using [GeometrySpace.norm] provided by the space
|
* Vector equality within given [precision] (using [GeometrySpace.norm] provided by the space
|
||||||
*/
|
*/
|
||||||
public fun <V : Vector> V.equalsVector(
|
public fun <V : Any, D : Comparable<D>> V.equalsVector(
|
||||||
space: GeometrySpace<V>,
|
space: GeometrySpace<V, D>,
|
||||||
other: V,
|
other: V,
|
||||||
precision: Double = DEFAULT_PRECISION,
|
precision: D = space.defaultPrecision,
|
||||||
): Boolean = with(space) {
|
): Boolean = with(space) {
|
||||||
norm(this@equalsVector - other) < precision
|
norm(this@equalsVector - other) < precision
|
||||||
}
|
}
|
||||||
@ -35,22 +22,22 @@ public fun <V : Vector> V.equalsVector(
|
|||||||
*/
|
*/
|
||||||
public fun Float64Vector2D.equalsVector(
|
public fun Float64Vector2D.equalsVector(
|
||||||
other: Float64Vector2D,
|
other: Float64Vector2D,
|
||||||
precision: Double = DEFAULT_PRECISION,
|
precision: Double = Euclidean3DSpace.defaultPrecision,
|
||||||
): Boolean = equalsVector(Euclidean2DSpace, other, precision)
|
): Boolean = equalsVector(Euclidean2DSpace, other, precision)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vector equality using Euclidian L2 norm and given [precision]
|
* Vector equality using Euclidean L2 norm and given [precision]
|
||||||
*/
|
*/
|
||||||
public fun Float64Vector3D.equalsVector(
|
public fun Float64Vector3D.equalsVector(
|
||||||
other: Float64Vector3D,
|
other: Float64Vector3D,
|
||||||
precision: Double = DEFAULT_PRECISION,
|
precision: Double = Euclidean3DSpace.defaultPrecision,
|
||||||
): Boolean = equalsVector(Euclidean3DSpace, other, precision)
|
): Boolean = equalsVector(Euclidean3DSpace, other, precision)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Line equality using [GeometrySpace.norm] provided by the [space] and given [precision]
|
* Line equality using [GeometrySpace.norm] provided by the [space] and given [precision]
|
||||||
*/
|
*/
|
||||||
public fun <V : Vector> LineSegment<V>.equalsLine(
|
public fun <V : Any, D : Comparable<D>> LineSegment<V>.equalsLine(
|
||||||
space: GeometrySpace<V>,
|
space: GeometrySpace<V, D>,
|
||||||
other: LineSegment<V>,
|
other: LineSegment<V>,
|
||||||
precision: Double = DEFAULT_PRECISION,
|
precision: D = space.defaultPrecision,
|
||||||
): Boolean = begin.equalsVector(space, other.begin, precision) && end.equalsVector(space, other.end, precision)
|
): Boolean = begin.equalsVector(space, other.begin, precision) && end.equalsVector(space, other.end, precision)
|
@ -36,13 +36,13 @@ fun assertVectorEquals(expected: DoubleVector3D, actual: DoubleVector3D, absolut
|
|||||||
assertEquals(expected.z, actual.z, absoluteTolerance)
|
assertEquals(expected.z, actual.z, absoluteTolerance)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <V : Vector> GeometrySpace<V>.isCollinear(a: V, b: V, absoluteTolerance: Double = 1e-6): Boolean {
|
fun <V : Any, D: Comparable<D>> GeometrySpace<V, D>.isCollinear(a: V, b: V, absoluteTolerance: D = defaultPrecision): Boolean {
|
||||||
val aDist = a.distanceTo(zero)
|
val aDist = a.distanceTo(zero)
|
||||||
val bDist = b.distanceTo(zero)
|
val bDist = b.distanceTo(zero)
|
||||||
return abs(aDist) < absoluteTolerance || abs(bDist) < absoluteTolerance || abs(abs((a dot b) / (aDist * bDist)) - 1) < absoluteTolerance
|
return aDist < absoluteTolerance || bDist < absoluteTolerance || abs(abs((a dot b) / (aDist * bDist)) - 1) < absoluteTolerance
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <V : Vector> GeometrySpace<V>.isOrthogonal(a: V, b: V, absoluteTolerance: Double = 1e-6): Boolean =
|
fun <V : Any> GeometrySpace<V,*>.isOrthogonal(a: V, b: V, absoluteTolerance: Double = 1e-6): Boolean =
|
||||||
abs(a dot b) < absoluteTolerance
|
abs(a dot b) < absoluteTolerance
|
||||||
|
|
||||||
fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001):
|
fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001):
|
||||||
|
@ -6,15 +6,16 @@
|
|||||||
import space.kscience.kmath.geometry.GeometrySpace
|
import space.kscience.kmath.geometry.GeometrySpace
|
||||||
import space.kscience.kmath.geometry.Line
|
import space.kscience.kmath.geometry.Line
|
||||||
import space.kscience.kmath.geometry.LineSegment
|
import space.kscience.kmath.geometry.LineSegment
|
||||||
import space.kscience.kmath.geometry.Vector
|
|
||||||
import space.kscience.kmath.operations.Group
|
import space.kscience.kmath.operations.Group
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a line, containing this [LineSegment]
|
* Get a line, containing this [LineSegment]
|
||||||
*/
|
*/
|
||||||
context(Group<V>) public val <V : Vector> LineSegment<V>.line: Line<V> get() = Line(begin, end - begin)
|
context(Group<V>)
|
||||||
|
public val <V : Any> LineSegment<V>.line: Line<V> get() = Line(begin, end - begin)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a length of a line segment
|
* Get a length of a line segment
|
||||||
*/
|
*/
|
||||||
context(GeometrySpace<V>) public val <V : Vector> LineSegment<V>.length: Double get() = norm(end - begin)
|
context(GeometrySpace<V>)
|
||||||
|
public val <V : Any> LineSegment<V>.length: Double get() = norm(end - begin)
|
Loading…
Reference in New Issue
Block a user