Add geodetic distance measurement.

This commit is contained in:
Alexander Nozik 2022-08-29 22:12:03 +03:00
parent e0cc0bc60b
commit 9ffc9d3d67
No known key found for this signature in database
GPG Key ID: F7FCF2DD25C71357
2 changed files with 28 additions and 38 deletions

View File

@ -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))
//}

View File

@ -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)