Add toString to curves and correct rounding normalization for angles
This commit is contained in:
parent
2b01b8e316
commit
6decba8e83
@ -10,7 +10,7 @@ val ktorVersion by extra("2.0.3")
|
||||
|
||||
allprojects {
|
||||
group = "center.sciprog"
|
||||
version = "0.1.0-dev-6"
|
||||
version = "0.1.0-dev-7"
|
||||
}
|
||||
|
||||
ksciencePublish{
|
||||
|
@ -7,6 +7,7 @@ package center.sciprog.maps.coordinates
|
||||
|
||||
import kotlin.jvm.JvmInline
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.floor
|
||||
|
||||
// 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())
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
is Degrees -> value.mod(360.0).degrees
|
||||
is Radians -> value.mod(PI * 2).radians
|
||||
}
|
||||
public fun Angle.normalized(center: Angle = Angle.pi): Angle =
|
||||
this - Angle.piTimes2 * floor((radians.value + PI - center.radians.value) / PI/2)
|
||||
|
||||
public fun abs(angle: Angle): Angle = if (angle < Angle.zero) -angle else angle
|
@ -1,7 +1,5 @@
|
||||
package center.sciprog.maps.coordinates
|
||||
|
||||
import kotlin.math.PI
|
||||
|
||||
/**
|
||||
* Geodetic coordinated
|
||||
*/
|
||||
@ -9,10 +7,10 @@ public class GeodeticMapCoordinates(
|
||||
public val latitude: Angle,
|
||||
longitude: Angle,
|
||||
) {
|
||||
public val longitude: Radians = longitude.radians.value.rem(PI / 2).radians
|
||||
public val longitude: Angle = longitude.normalized(Angle.zero)
|
||||
|
||||
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 {
|
||||
|
@ -10,11 +10,15 @@ import kotlin.math.*
|
||||
* @param forward coordinate of a start point with forward 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 backward: GmcPose,
|
||||
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)
|
||||
|
||||
@ -222,6 +226,8 @@ public fun GeoEllipsoid.curveBetween(start: Gmc, end: Gmc, precision: Double = 1
|
||||
val a = equatorRadius
|
||||
val b = polarRadius
|
||||
|
||||
if(start == end) error("Can't compute a curve because start and end coincide at $start")
|
||||
|
||||
// get parameters as radians
|
||||
val phi1 = start.latitude
|
||||
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 b2 = b.kilometers * b.kilometers
|
||||
val a2b2b2 = (a2 - b2) / b2
|
||||
val omega: Radians = lambda2 - lambda1
|
||||
val omega: Angle = lambda2 - lambda1
|
||||
val tanphi1: Double = tan(phi1)
|
||||
val tanU1 = (1.0 - f) * tanphi1
|
||||
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 deltasigma = 0.0
|
||||
var lambda0: Radians
|
||||
var lambda0: Angle
|
||||
var converged = false
|
||||
for (i in 0..19) {
|
||||
lambda0 = lambda
|
||||
@ -326,8 +332,7 @@ public fun GeoEllipsoid.curveBetween(start: Gmc, end: Gmc, precision: Double = 1
|
||||
alpha1 = 0.0.radians
|
||||
alpha2 = pi.radians
|
||||
} else {
|
||||
alpha1 = Double.NaN.radians
|
||||
alpha2 = Double.NaN.radians
|
||||
error("Start and end point coinside.")
|
||||
}
|
||||
} else {
|
||||
// eq. 20
|
||||
|
@ -8,5 +8,9 @@ class AngleTest {
|
||||
fun normalization(){
|
||||
assertEquals(30.degrees, 390.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))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user