Skip to content

Commit

Permalink
beginnings of untested mgrs implementation (chat gpt so probably wron…
Browse files Browse the repository at this point in the history
…g ;-) )
  • Loading branch information
jillesvangurp committed Nov 14, 2023
1 parent 66e2a32 commit b753eac
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
94 changes: 94 additions & 0 deletions src/commonMain/kotlin/com/jillesvangurp/geo/mgrs.kt
@@ -0,0 +1,94 @@
package com.jillesvangurp.geo

import kotlin.math.roundToInt


private val eastingLetters = "ABCDEFGHJKLMNPQRSTUVWXYZ" // Excludes I and O
private val northingLetters = "ABCDEFGHJKLMNPQRSTUV" // Excludes I and O

data class MgrsCoordinate(
val longitudeZone: Int,
val latitudeZoneLetter: Char,
val eastingLetter: Char,
val northingLetter: Char,
val easting: Int,
val northing: Int
) {
override fun toString(): String {
return "$longitudeZone$latitudeZoneLetter $eastingLetter$northingLetter $easting $northing"
}
}

fun UtmCoordinate.convertUTMToMGRS(): MgrsCoordinate {
val eastingLetter = getEastingLetter(longitudeZone, easting.toInt())
val northingLetter = getNorthingLetter(northing.toInt(), latitudeZoneLetter)

val eastingValue = (easting % 100000).roundToInt()
val northingValue = (northing % 100000).roundToInt()

return MgrsCoordinate(
longitudeZone,
latitudeZoneLetter,
eastingLetter,
northingLetter,
eastingValue.toString().padStart(5, '0').toInt(),
northingValue.toString().padStart(5, '0').toInt()
)
}

private fun getEastingLetter(zoneNumber: Int, easting: Int): Char {
val gridEasting = (easting / 100000)
val index = (gridEasting - 1 + (zoneNumber - 1) * 8) % eastingLetters.length
return eastingLetters[index]
}

//private fun getNorthingLetter(zoneNumber: Int, northing: Int): Char {
// val gridNorthing = (northing / 100000)
// val index = (gridNorthing - 1 + (zoneNumber - 1) * 2) % northingLetters.length
// return northingLetters[index]
//}

private fun getNorthingLetter(northing: Int, latitudeZoneLetter: Char): Char {
// Northing value should be adjusted for the false northing if in the southern hemisphere.
val adjustedNorthing = if (latitudeZoneLetter < 'N') northing + 10000000 else northing
// The northingLetters string starts with 'A' for 0m N, so no need to subtract 1 from the index.
val index = (adjustedNorthing / 100000) % northingLetters.length
return northingLetters[index]
}


fun convertMGRSToUTM(
zoneNumber: Int,
zoneLetter: Char,
gridSquare: String,
easting: Int,
northing: Int
): UtmCoordinate {
val eastingLetter = gridSquare[0]
val northingLetter = gridSquare[1]

val eastingOffset = getEastingOffset(eastingLetter, zoneNumber)
val northingOffset = getNorthingOffset(northingLetter, zoneNumber, zoneLetter)

val fullEasting = eastingOffset * 100000 + easting
val fullNorthing = northingOffset * 100000 + northing

return UtmCoordinate(zoneNumber, zoneLetter, fullEasting.toDouble(), fullNorthing.toDouble())
}

private fun getEastingOffset(eastingLetter: Char, zoneNumber: Int): Int {
val eastingIndex = eastingLetters.indexOf(eastingLetter)
return (eastingIndex + 1 - (zoneNumber - 1) * 8 + eastingLetters.length) % eastingLetters.length
}

private fun getNorthingOffset(northingLetter: Char, zoneNumber: Int, zoneLetter: Char): Int {
var northingIndex = northingLetters.indexOf(northingLetter)
northingIndex = (northingIndex + 1 - (zoneNumber - 1) * 2 + northingLetters.length) % northingLetters.length

// Adjust for the latitude band
val northingBase = "CDEFGHJKLMNPQRSTUVWX".indexOf(zoneLetter.uppercaseChar()) * 8
return (northingBase + northingIndex) % northingLetters.length
}



13 changes: 13 additions & 0 deletions src/commonTest/kotlin/com/jillesvangurp/geogeometry/MGRSTest.kt
@@ -0,0 +1,13 @@
package com.jillesvangurp.geogeometry

import com.jillesvangurp.geo.convertUTMToMGRS
import com.jillesvangurp.geo.toUtmCoordinate
import kotlin.test.Test

class MGRSTest {
@Test
fun shouldCalculateMgrsForBrandenburgerTor() {
val mgrs = brandenBurgerGate.toUtmCoordinate().convertUTMToMGRS()
println(mgrs)
}
}

0 comments on commit b753eac

Please sign in to comment.