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