Skip to content

Commit 9200998

Browse files
committed
add equirectangular distance, rename function to distanceToLine for clarity
1 parent 2f13850 commit 9200998

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

src/commonMain/kotlin/com/jillesvangurp/geo/GeoGeometry.kt

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ class GeoGeometry {
299299
* double.
300300
*
301301
* @param d a double
302-
* @param decimals the number of desired decimals after the .
302+
* @param decimals the number of desired decimals after the dot
303303
* @return d rounded to the specified precision
304304
*/
305305
fun roundToDecimals(d: Double, decimals: Int): Double {
@@ -589,6 +589,23 @@ class GeoGeometry {
589589
return distance(p1[1], p1[0], p2[1], p2[0])
590590
}
591591

592+
/**
593+
* Cheap but not very precise over larger distances
594+
*/
595+
fun equirectangularDistance(
596+
lat1: Double,
597+
lon1: Double,
598+
lat2: Double,
599+
lon2: Double
600+
): Double {
601+
val x = toRadians(lon2 - lon1) * cos(toRadians((lat1 + lat2) / 2))
602+
val y = toRadians(lat2 - lat1)
603+
return sqrt(x * x + y * y) * EARTH_RADIUS_METERS
604+
}
605+
606+
fun equirectangularDistance(p1: PointCoordinates, p2: PointCoordinates): Double =
607+
equirectangularDistance(p1[1], p1[0], p2[1], p2[0])
608+
592609
/**
593610
* Calculate distance in meters using the Vicenty algorithm.
594611
*
@@ -675,7 +692,7 @@ class GeoGeometry {
675692
* @param p point
676693
* @return the distance of the point to the line
677694
*/
678-
fun distance(l1: PointCoordinates, l2: PointCoordinates, p: PointCoordinates): Double {
695+
fun distanceToLine(l1: PointCoordinates, l2: PointCoordinates, p: PointCoordinates): Double {
679696
return distance(l1[1], l1[0], l2[1], l2[0], p[1], p[0])
680697
}
681698

@@ -695,7 +712,7 @@ class GeoGeometry {
695712
var last = lineStringCoordinates[0]
696713
for (i in 1 until lineStringCoordinates.size) {
697714
val current = lineStringCoordinates[i]
698-
val distance = distance(last, current, pointCoordinates)
715+
val distance = distanceToLine(last, current, pointCoordinates)
699716
minDistance = min(minDistance, distance)
700717
last = current
701718
}
@@ -1356,11 +1373,11 @@ class GeoGeometry {
13561373
var dmax = 0.0
13571374
var index = 0
13581375
if (points.size == 3) {
1359-
dmax = distance(points[0], points[points.size - 1], points[1]) // edge case
1376+
dmax = distanceToLine(points[0], points[points.size - 1], points[1]) // edge case
13601377
}
13611378

13621379
for (i in 2 until points.size - 1) {
1363-
val d = distance(points[0], points[points.size - 1], points[i])
1380+
val d = distanceToLine(points[0], points[points.size - 1], points[i])
13641381
if (d > dmax) {
13651382
index = i
13661383
dmax = d

src/commonTest/kotlin/com/jillesvangurp/geogeometry/GeoGeometryMigratedTests.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import com.jillesvangurp.geo.GeoGeometry.Companion.boundingBox
88
import com.jillesvangurp.geo.GeoGeometry.Companion.circle2polygon
99
import com.jillesvangurp.geo.GeoGeometry.Companion.contains
1010
import com.jillesvangurp.geo.GeoGeometry.Companion.distance
11+
import com.jillesvangurp.geo.GeoGeometry.Companion.distanceToLine
1112
import com.jillesvangurp.geo.GeoGeometry.Companion.distanceToLineString
1213
import com.jillesvangurp.geo.GeoGeometry.Companion.distanceToMultiPolygon
1314
import com.jillesvangurp.geo.GeoGeometry.Companion.distanceToPolygon
15+
import com.jillesvangurp.geo.GeoGeometry.Companion.equirectangularDistance
1416
import com.jillesvangurp.geo.GeoGeometry.Companion.expandPolygon
1517
import com.jillesvangurp.geo.GeoGeometry.Companion.filterNoiseFromPointCloud
1618
import com.jillesvangurp.geo.GeoGeometry.Companion.linesCross
@@ -71,6 +73,15 @@ class GeoGeometryMigratedTests {
7173
doubleArrayOf(-1.0, 1.0)
7274
)
7375

76+
@Test
77+
fun shouldCalculateDistances() {
78+
val d1 = distance(senefelderPlatz, rosenthalerPlatz)
79+
val d2 = vicentyDistance(senefelderPlatz, rosenthalerPlatz)
80+
val d3 = equirectangularDistance(senefelderPlatz, rosenthalerPlatz)
81+
abs(d1-d2) shouldBeLessThan 3.0 // vicenty is the most correct, havesine and quirectangular have similar bias
82+
abs(d1-d3) shouldBeLessThan 1.0
83+
}
84+
7485
@Test
7586
fun shouldCheckThatLinesCross() {
7687
// should intersect
@@ -527,7 +538,7 @@ class GeoGeometryMigratedTests {
527538

528539
val distance = distance(x1, y1, x2, y2, px, py)
529540
val distance2 =
530-
distance(doubleArrayOf(y1, x1), doubleArrayOf(y2, x2), doubleArrayOf(py, px))
541+
distanceToLine(doubleArrayOf(y1, x1), doubleArrayOf(y2, x2), doubleArrayOf(py, px))
531542
distance shouldBe distance2
532543
round(distance) shouldBe expectedDistance
533544

0 commit comments

Comments
 (0)