Add geodetic distance measurement.
This commit is contained in:
parent
e0cc0bc60b
commit
9ffc9d3d67
@ -1,7 +1,8 @@
|
||||
package center.sciprog.maps.coordinates
|
||||
|
||||
import center.sciprog.maps.coordinates.GeoEllipsoid.Companion.greatCircleAngleBetween
|
||||
import kotlin.math.*
|
||||
import kotlin.math.acos
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
|
||||
public class GeoEllipsoid(public val equatorRadius: Distance, public val polarRadius: Distance) {
|
||||
@ -35,12 +36,12 @@ public class GeoEllipsoid(public val equatorRadius: Distance, public val polarRa
|
||||
polarRadius = Distance(6378.137)
|
||||
)
|
||||
|
||||
/**
|
||||
* https://en.wikipedia.org/wiki/Great-circle_distance
|
||||
*/
|
||||
public fun greatCircleAngleBetween(r1: GMC, r2: GMC): Radians = acos(
|
||||
sin(r1.latitude) * sin(r2.latitude) + cos(r1.latitude) * cos(r2.latitude) * cos(r1.longitude - r2.longitude)
|
||||
).radians
|
||||
// /**
|
||||
// * https://en.wikipedia.org/wiki/Great-circle_distance
|
||||
// */
|
||||
// public fun greatCircleAngleBetween(r1: GMC, r2: GMC): Radians = acos(
|
||||
// sin(r1.latitude) * sin(r2.latitude) + cos(r1.latitude) * cos(r2.latitude) * cos(r1.longitude - r2.longitude)
|
||||
// ).radians
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,22 +52,22 @@ internal fun GeoEllipsoid.reducedRadius(latitude: Angle): Distance {
|
||||
val reducedLatitudeTan = (1 - f) * tan(latitude)
|
||||
return equatorRadius / sqrt(1.0 + reducedLatitudeTan.pow(2))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compute distance between two map points using giv
|
||||
* https://en.wikipedia.org/wiki/Geographical_distance#Lambert's_formula_for_long_lines
|
||||
*/
|
||||
public fun GeoEllipsoid.lambertDistanceBetween(r1: GMC, r2: GMC): Distance {
|
||||
val s = greatCircleAngleBetween(r1, r2)
|
||||
|
||||
val b1: Double = (1 - f) * tan(r1.latitude)
|
||||
val b2: Double = (1 - f) * tan(r2.latitude)
|
||||
val p = (b1 + b2) / 2
|
||||
val q = (b2 - b1) / 2
|
||||
|
||||
val x = (s.value - sin(s)) * sin(p).pow(2) * cos(q).pow(2) / cos(s / 2).pow(2)
|
||||
val y = (s.value + sin(s)) * cos(p).pow(2) * sin(q).pow(2) / sin(s / 2).pow(2)
|
||||
|
||||
return equatorRadius * (s.value - f / 2 * (x + y))
|
||||
}
|
||||
//
|
||||
//
|
||||
///**
|
||||
// * Compute distance between two map points using giv
|
||||
// * https://en.wikipedia.org/wiki/Geographical_distance#Lambert's_formula_for_long_lines
|
||||
// */
|
||||
//public fun GeoEllipsoid.lambertDistanceBetween(r1: GMC, r2: GMC): Distance {
|
||||
// val s = greatCircleAngleBetween(r1, r2)
|
||||
//
|
||||
// val b1: Double = (1 - f) * tan(r1.latitude)
|
||||
// val b2: Double = (1 - f) * tan(r2.latitude)
|
||||
// val p = (b1 + b2) / 2
|
||||
// val q = (b2 - b1) / 2
|
||||
//
|
||||
// val x = (s.value - sin(s)) * sin(p).pow(2) * cos(q).pow(2) / cos(s / 2).pow(2)
|
||||
// val y = (s.value + sin(s)) * cos(p).pow(2) * sin(q).pow(2) / sin(s / 2).pow(2)
|
||||
//
|
||||
// return equatorRadius * (s.value - f / 2 * (x + y))
|
||||
//}
|
@ -15,17 +15,6 @@ internal class DistanceTest {
|
||||
assertEquals(298.257223563, GeoEllipsoid.WGS84.inverseF, 1e-6)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
fun greatCircleDistance() {
|
||||
assertEquals(
|
||||
expected = 632.035,
|
||||
actual = GeoEllipsoid.greatCircleAngleBetween(moscow, spb).value *
|
||||
GeoEllipsoid.WGS84.equatorRadius.kilometers,
|
||||
absoluteTolerance = 0.1
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun curveBetween() {
|
||||
val curve = GeoEllipsoid.WGS84.curveBetween(moscow, spb)
|
||||
|
Loading…
Reference in New Issue
Block a user