From 875e32679bc53f7e27814b6d067594f38de53ba6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 12 Apr 2023 11:39:28 +0300 Subject: [PATCH] [WIP] geometry refactor --- CHANGELOG.md | 1 + build.gradle.kts | 8 ++--- .../space/kscience/kmath/geometry/Circle2D.kt | 6 ++-- .../kmath/geometry/Euclidean2DSpace.kt | 7 +++-- .../kmath/geometry/Euclidean3DSpace.kt | 6 ++-- .../kscience/kmath/geometry/GeometrySpace.kt | 23 ++++++++------ .../space/kscience/kmath/geometry/Line.kt | 14 ++++----- .../kscience/kmath/geometry/projections.kt | 4 +-- .../{floatPrecision.kt => vectorPrecision.kt} | 31 ++++++------------- .../kscience/kmath/geometry/testUtils.kt | 6 ++-- .../kscience/kmath/geometry/lineExtensions.kt | 7 +++-- 11 files changed, 56 insertions(+), 57 deletions(-) rename kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/{floatPrecision.kt => vectorPrecision.kt} (51%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 998e6daae..073eaaba2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ - Algebra now has an obligatory `bufferFactory` (#477). ### Changed +- Removed marker `Vector` type for geometry - Geometry uses type-safe angles - Tensor operations switched to prefix notation - Row-wise and column-wise ND shapes in the core diff --git a/build.gradle.kts b/build.gradle.kts index ec67eaa54..e061d007c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ allprojects { } group = "space.kscience" - version = "0.3.1-dev-RC" + version = "0.3.2-dev-" } subprojects { @@ -66,10 +66,10 @@ ksciencePublish { } github("kmath", "SciProgCentre") space( - if (isInDevelopment) { - "https://maven.pkg.jetbrains.space/spc/p/sci/dev" - } else { + if (findProperty("production") == "true" || !isInDevelopment) { "https://maven.pkg.jetbrains.space/spc/p/sci/maven" + } else { + "https://maven.pkg.jetbrains.space/spc/p/sci/dev" } ) sonatype() diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt index d37ed45c0..1a4cb6734 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Circle2D.kt @@ -6,8 +6,10 @@ package space.kscience.kmath.geometry import kotlinx.serialization.Serializable -import space.kscience.kmath.geometry.Euclidean2DSpace.distanceTo -import kotlin.math.* +import kotlin.math.PI + +interface Circle + /** * A circle in 2D space diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt index 3df8dba7b..012b5b73a 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean2DSpace.kt @@ -17,7 +17,7 @@ import space.kscience.kmath.operations.ScaleOperations import kotlin.math.pow import kotlin.math.sqrt -public interface Vector2D : Point, Vector { +public interface Vector2D : Point { public val x: T public val y: T override val size: Int get() = 2 @@ -47,7 +47,8 @@ public val Vector2D.r: Double get() = Euclidean2DSpace.norm(this) /** * 2D Euclidean space */ -public object Euclidean2DSpace : GeometrySpace, +public object Euclidean2DSpace : + GeometrySpace, ScaleOperations, Norm { @@ -87,4 +88,6 @@ public object Euclidean2DSpace : GeometrySpace, public val xAxis: DoubleVector2D = vector(1.0, 0.0) public val yAxis: DoubleVector2D = vector(0.0, 1.0) + + override val defaultPrecision: Double = 1e-6 } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt index 3059cefe6..ce19d20a5 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Euclidean3DSpace.kt @@ -18,7 +18,7 @@ import space.kscience.kmath.structures.Buffer import kotlin.math.pow import kotlin.math.sqrt -public interface Vector3D : Point, Vector { +public interface Vector3D : Point { public val x: T public val y: T public val z: T @@ -55,7 +55,7 @@ public typealias Float64Vector3D = Vector3D public val DoubleVector3D.r: Double get() = Euclidean3DSpace.norm(this) -public object Euclidean3DSpace : GeometrySpace, ScaleOperations, +public object Euclidean3DSpace : GeometrySpace, ScaleOperations, Norm { @Serializable @@ -146,4 +146,6 @@ public object Euclidean3DSpace : GeometrySpace, ScaleOperations< public val xAxis: DoubleVector3D = vector(1.0, 0.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) + + override val defaultPrecision: Double = 1e-6 } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt index d6d7e5725..77c3b3a92 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/GeometrySpace.kt @@ -9,23 +9,26 @@ import space.kscience.kmath.operations.Group import space.kscience.kmath.operations.Norm import space.kscience.kmath.operations.ScaleOperations -public interface Vector - -public interface GeometrySpace : Group, ScaleOperations, Norm { +/** + * A geometry vector space + * @param V the type of vector object + * @param D the type of distance + */ +public interface GeometrySpace> : Group, ScaleOperations, Norm { /** * L2 distance */ - public fun V.distanceTo(other: V): Double + public fun V.distanceTo(other: V): D /** * Scalar product */ public infix fun V.dot(other: V): Double - public companion object{ - /** - * Default precision for geometry objects comparison - */ - internal const val DEFAULT_PRECISION = 1e-6 - } + /** + * Default precision for geometry objects comparison + */ + public val defaultPrecision: D + + public companion object } \ No newline at end of file diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt index a7f6ae35d..ed970b944 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/Line.kt @@ -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, * but its length does not affect line properties */ -public interface Line { +public interface Line { public val start: V public val direction: V } @Serializable @SerialName("Line") -private data class LineImpl(override val start: V, override val direction: V): Line +private data class LineImpl(override val start: V, override val direction: V) : Line -public fun Line(base: V, direction: V): Line = LineImpl(base, direction) +public fun Line(base: V, direction: V): Line = LineImpl(base, direction) public typealias Line2D = Line public typealias Line3D = Line @@ -29,7 +29,7 @@ public typealias Line3D = Line /** * A directed line segment between [begin] and [end] */ -public interface LineSegment { +public interface LineSegment { public val begin: V public val end: V } @@ -39,11 +39,11 @@ public interface LineSegment { */ @Serializable @SerialName("LineSegment") -private data class LineSegmentImpl(override val begin: V, override val end: V) : LineSegment +private data class LineSegmentImpl(override val begin: V, override val end: V) : LineSegment -public fun LineSegment(begin: V, end: V): LineSegment = LineSegmentImpl(begin, end) +public fun LineSegment(begin: V, end: V): LineSegment = LineSegmentImpl(begin, end) -public fun LineSegment.line(algebra: GeometrySpace): Line = with(algebra) { +public fun LineSegment.line(algebra: GeometrySpace): Line = with(algebra) { Line(begin, end - begin) } diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt index c5c3487a1..a983e6837 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/projections.kt @@ -12,7 +12,7 @@ package space.kscience.kmath.geometry * @param vector to project * @param line line to which vector should be projected */ -public fun GeometrySpace.projectToLine(vector: V, line: Line): V = with(line) { +public fun GeometrySpace.projectToLine(vector: V, line: Line): V = with(line) { start + (direction dot (vector - start)) / (direction dot direction) * direction } @@ -23,5 +23,5 @@ public fun GeometrySpace.projectToLine(vector: V, line: Line) * @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 */ -public fun GeometrySpace.projectAlong(vector: V, normal: V, base: V): V = +public fun GeometrySpace.projectAlong(vector: V, normal: V, base: V): V = vector + normal * ((base - vector) dot normal) / (normal dot normal) diff --git a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/vectorPrecision.kt similarity index 51% rename from kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt rename to kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/vectorPrecision.kt index ea46ab90f..0c6816186 100644 --- a/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/floatPrecision.kt +++ b/kmath-geometry/src/commonMain/kotlin/space/kscience/kmath/geometry/vectorPrecision.kt @@ -5,27 +5,14 @@ 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 */ -public fun V.equalsVector( - space: GeometrySpace, +public fun > V.equalsVector( + space: GeometrySpace, other: V, - precision: Double = DEFAULT_PRECISION, + precision: D = space.defaultPrecision, ): Boolean = with(space) { norm(this@equalsVector - other) < precision } @@ -35,22 +22,22 @@ public fun V.equalsVector( */ public fun Float64Vector2D.equalsVector( other: Float64Vector2D, - precision: Double = DEFAULT_PRECISION, + precision: Double = Euclidean3DSpace.defaultPrecision, ): 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( other: Float64Vector3D, - precision: Double = DEFAULT_PRECISION, + precision: Double = Euclidean3DSpace.defaultPrecision, ): Boolean = equalsVector(Euclidean3DSpace, other, precision) /** * Line equality using [GeometrySpace.norm] provided by the [space] and given [precision] */ -public fun LineSegment.equalsLine( - space: GeometrySpace, +public fun > LineSegment.equalsLine( + space: GeometrySpace, other: LineSegment, - precision: Double = DEFAULT_PRECISION, + precision: D = space.defaultPrecision, ): Boolean = begin.equalsVector(space, other.begin, precision) && end.equalsVector(space, other.end, precision) \ No newline at end of file diff --git a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt index c62af3cd3..6796b291f 100644 --- a/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt +++ b/kmath-geometry/src/commonTest/kotlin/space/kscience/kmath/geometry/testUtils.kt @@ -36,13 +36,13 @@ fun assertVectorEquals(expected: DoubleVector3D, actual: DoubleVector3D, absolut assertEquals(expected.z, actual.z, absoluteTolerance) } -fun GeometrySpace.isCollinear(a: V, b: V, absoluteTolerance: Double = 1e-6): Boolean { +fun > GeometrySpace.isCollinear(a: V, b: V, absoluteTolerance: D = defaultPrecision): Boolean { val aDist = a.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 GeometrySpace.isOrthogonal(a: V, b: V, absoluteTolerance: Double = 1e-6): Boolean = +fun GeometrySpace.isOrthogonal(a: V, b: V, absoluteTolerance: Double = 1e-6): Boolean = abs(a dot b) < absoluteTolerance fun Double.equalFloat(other: Double, maxFloatDelta: Double = 0.000001): diff --git a/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt b/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt index 5fcd2b23e..cf204f080 100644 --- a/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt +++ b/kmath-geometry/src/jvmMain/kotlin/space/kscience/kmath/geometry/lineExtensions.kt @@ -6,15 +6,16 @@ import space.kscience.kmath.geometry.GeometrySpace import space.kscience.kmath.geometry.Line import space.kscience.kmath.geometry.LineSegment -import space.kscience.kmath.geometry.Vector import space.kscience.kmath.operations.Group /** * Get a line, containing this [LineSegment] */ -context(Group) public val LineSegment.line: Line get() = Line(begin, end - begin) +context(Group) +public val LineSegment.line: Line get() = Line(begin, end - begin) /** * Get a length of a line segment */ -context(GeometrySpace) public val LineSegment.length: Double get() = norm(end - begin) \ No newline at end of file +context(GeometrySpace) +public val LineSegment.length: Double get() = norm(end - begin) \ No newline at end of file