Last active
May 25, 2024 08:39
-
-
Save dacr/4bd607523c8ddf30459b5a96d83baede to your computer and use it in GitHub Desktop.
geo conversions / published by https://github.com/dacr/code-examples-manager #0b3d43a7-3e8a-4bca-a768-3a28bd84c3ea/b1b1ff20feb0a8e192fd0bf8ee1f0dc47e848494
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// summary : geo conversions | |
// keywords : scala, gps, dms, @testable | |
// publish : gist | |
// authors : David Crosson | |
// license : Apache NON-AI License Version 2.0 (https://raw.githubusercontent.com/non-ai-licenses/non-ai-licenses/main/NON-AI-APACHE2) | |
// id : 0b3d43a7-3e8a-4bca-a768-3a28bd84c3ea | |
// created-on : 2022-03-14T18:31:29+01:00 | |
// managed-by : https://github.com/dacr/code-examples-manager | |
// run-with : scala-cli $file | |
// --------------------- | |
//> using scala "3.4.2" | |
//> using dep "org.scalatest::scalatest:3.2.16" | |
//> using objectWrapper | |
// --------------------- | |
import org.scalatest.* | |
import flatspec.* | |
import matchers.* | |
import scala.util.{Failure, Success, Try} | |
import org.scalatest.TryValues.* | |
import java.util.Locale | |
/* | |
- Positive latitudes are north of the equator | |
- Negative latitudes are south of the equator | |
- Positive longitudes are east of the Prime Meridian | |
- Negative longitudes are west of the Prime Meridian. | |
- Latitude and longitude are usually expressed in that sequence, latitude before longitude. | |
- Reference NSEW is mandatory to give the right value sign (because -0° is not valid of course) | |
*/ | |
val dmsRE = """[-+]?(\d+)[°]\s*(\d+)['′]\s*(\d+(?:[.,]\d+)?)(?:(?:")|(?:'')|(?:′′)|(?:″))""".r | |
def convert(d: Double, m: Double, s: Double): Double = d + m / 60d + s / 3600d | |
def degreesMinuteSecondsToDecimalDegrees( | |
dms: String, | |
ref: String | |
): Try[Double] = Try { | |
val dd = dms.trim match { | |
case dmsRE(d, m, s) => convert(d.toDouble, m.toDouble, s.replaceAll(",", ".").toDouble) | |
} | |
if ("NE".contains(ref.trim.toUpperCase.head)) dd else -dd | |
} | |
class GeoTest extends AnyFlatSpec with should.Matchers { | |
"degrees minutes seconds" can "be decoded to decimal degrees" in { | |
val toTest = List( | |
("N", "1° 00′ 0″", 1.0d), | |
("N", "0° 06′ 0″", 0.1d), | |
("N", "0° 00′ 36″", 0.01d), | |
("N", "0° 00′ 0.036″", 0.00001), | |
("E", "30° 15' 50\"", 30.263888889d), | |
("S", "3°58'24\"", -3.9733333333333336d), | |
("S", "-3°58'24\"", -3.9733333333333336d), | |
("N", "48° 18' 57,67\"", 48.31601944444444d) | |
) | |
toTest.foreach((ref, dms, dd) => { | |
degreesMinuteSecondsToDecimalDegrees(dms, ref).success.value should equal(dd +- .000000001) | |
}) | |
} | |
} | |
org.scalatest.tools.Runner.main(Array("-oDF", "-s", classOf[GeoTest].getName)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment