Add toString to curves and correct rounding normalization for angles

This commit is contained in:
Alexander Nozik 2022-09-16 12:59:58 +03:00
parent 2b01b8e316
commit 6decba8e83
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
5 changed files with 22 additions and 16 deletions

View File

@ -10,7 +10,7 @@ val ktorVersion by extra("2.0.3")
allprojects { allprojects {
group = "center.sciprog" group = "center.sciprog"
version = "0.1.0-dev-6" version = "0.1.0-dev-7"
} }
ksciencePublish{ ksciencePublish{

View File

@ -7,6 +7,7 @@ package center.sciprog.maps.coordinates
import kotlin.jvm.JvmInline import kotlin.jvm.JvmInline
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.floor
// Taken from KMath dev version, to be used directly in the future // Taken from KMath dev version, to be used directly in the future
@ -82,11 +83,9 @@ public value class Degrees(public val value: Double) : Angle {
public val Number.degrees: Degrees get() = Degrees(toDouble()) public val Number.degrees: Degrees get() = Degrees(toDouble())
/** /**
* Normalized angle to (0, 2PI) for radians or (0, 360) for degrees. * Normalized angle 2 PI range symmetric around [center]. By default, uses (0, 2PI) range.
*/ */
public fun Angle.normalized(): Angle = when (this) { public fun Angle.normalized(center: Angle = Angle.pi): Angle =
is Degrees -> value.mod(360.0).degrees this - Angle.piTimes2 * floor((radians.value + PI - center.radians.value) / PI/2)
is Radians -> value.mod(PI * 2).radians
}
public fun abs(angle: Angle): Angle = if (angle < Angle.zero) -angle else angle public fun abs(angle: Angle): Angle = if (angle < Angle.zero) -angle else angle

View File

@ -1,7 +1,5 @@
package center.sciprog.maps.coordinates package center.sciprog.maps.coordinates
import kotlin.math.PI
/** /**
* Geodetic coordinated * Geodetic coordinated
*/ */
@ -9,10 +7,10 @@ public class GeodeticMapCoordinates(
public val latitude: Angle, public val latitude: Angle,
longitude: Angle, longitude: Angle,
) { ) {
public val longitude: Radians = longitude.radians.value.rem(PI / 2).radians public val longitude: Angle = longitude.normalized(Angle.zero)
init { init {
require(latitude.radians.value in (-PI / 2)..(PI / 2)) { "Latitude $latitude is not in (-PI/2)..(PI/2)" } require(latitude in (-Angle.piDiv2)..(Angle.piDiv2)) { "Latitude $latitude is not in (-PI/2)..(PI/2)" }
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@ -10,11 +10,15 @@ import kotlin.math.*
* @param forward coordinate of a start point with forward direction * @param forward coordinate of a start point with forward direction
* @param backward coordinate of an end point with backward direction * @param backward coordinate of an end point with backward direction
*/ */
public class GmcCurve internal constructor( public class GmcCurve(
public val forward: GmcPose, public val forward: GmcPose,
public val backward: GmcPose, public val backward: GmcPose,
public val distance: Distance, public val distance: Distance,
) ){
override fun toString(): String {
return "GmcCurve(from: ${forward.coordinates}, to: ${backward.coordinates})"
}
}
public fun GmcCurve.reversed(): GmcCurve = GmcCurve(backward, forward, distance) public fun GmcCurve.reversed(): GmcCurve = GmcCurve(backward, forward, distance)
@ -222,6 +226,8 @@ public fun GeoEllipsoid.curveBetween(start: Gmc, end: Gmc, precision: Double = 1
val a = equatorRadius val a = equatorRadius
val b = polarRadius val b = polarRadius
if(start == end) error("Can't compute a curve because start and end coincide at $start")
// get parameters as radians // get parameters as radians
val phi1 = start.latitude val phi1 = start.latitude
val lambda1 = start.longitude val lambda1 = start.longitude
@ -232,7 +238,7 @@ public fun GeoEllipsoid.curveBetween(start: Gmc, end: Gmc, precision: Double = 1
val a2 = a.kilometers * a.kilometers val a2 = a.kilometers * a.kilometers
val b2 = b.kilometers * b.kilometers val b2 = b.kilometers * b.kilometers
val a2b2b2 = (a2 - b2) / b2 val a2b2b2 = (a2 - b2) / b2
val omega: Radians = lambda2 - lambda1 val omega: Angle = lambda2 - lambda1
val tanphi1: Double = tan(phi1) val tanphi1: Double = tan(phi1)
val tanU1 = (1.0 - f) * tanphi1 val tanU1 = (1.0 - f) * tanphi1
val U1: Double = atan(tanU1) val U1: Double = atan(tanU1)
@ -256,7 +262,7 @@ public fun GeoEllipsoid.curveBetween(start: Gmc, end: Gmc, precision: Double = 1
var sigma = 0.0 var sigma = 0.0
var deltasigma = 0.0 var deltasigma = 0.0
var lambda0: Radians var lambda0: Angle
var converged = false var converged = false
for (i in 0..19) { for (i in 0..19) {
lambda0 = lambda lambda0 = lambda
@ -326,8 +332,7 @@ public fun GeoEllipsoid.curveBetween(start: Gmc, end: Gmc, precision: Double = 1
alpha1 = 0.0.radians alpha1 = 0.0.radians
alpha2 = pi.radians alpha2 = pi.radians
} else { } else {
alpha1 = Double.NaN.radians error("Start and end point coinside.")
alpha2 = Double.NaN.radians
} }
} else { } else {
// eq. 20 // eq. 20

View File

@ -8,5 +8,9 @@ class AngleTest {
fun normalization(){ fun normalization(){
assertEquals(30.degrees, 390.degrees.normalized()) assertEquals(30.degrees, 390.degrees.normalized())
assertEquals(30.degrees, (-330).degrees.normalized()) assertEquals(30.degrees, (-330).degrees.normalized())
assertEquals(200.degrees, 200.degrees.normalized())
assertEquals(30.degrees, 390.degrees.normalized(Angle.zero))
assertEquals(30.degrees, (-330).degrees.normalized(Angle.zero))
assertEquals((-160).degrees, 200.degrees.normalized(Angle.zero))
} }
} }