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 {
|
allprojects {
|
||||||
group = "center.sciprog"
|
group = "center.sciprog"
|
||||||
version = "0.1.0-dev-6"
|
version = "0.1.0-dev-7"
|
||||||
}
|
}
|
||||||
|
|
||||||
ksciencePublish{
|
ksciencePublish{
|
||||||
|
@ -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
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user