From 6fe7f067baa04e1a5faa6e8545356cfd57d31803 Mon Sep 17 00:00:00 2001 From: miafg Date: Thu, 8 Dec 2016 16:56:39 -0500 Subject: [PATCH 1/2] Added WKT Parser to improve WKT.getEpsgCode Signed-off-by: miafg --- proj4/build.sbt | 1 + proj4/src/main/Proj4WKTQuestions.md | 11 + .../geotrellis/proj4/wkt/epsg.properties | 6 +- .../scala/geotrellis/proj4/io/wkt/WKT.scala | 77 ++- .../geotrellis/proj4/io/wkt/WKTParser.scala | 115 ++++ .../scala/geotrellis/proj4/io/wkt/WktCS.scala | 39 ++ .../proj4/io/wkt/WKTParserTest.scala | 632 ++++++++++++++++++ project/Dependencies.scala | 2 + 8 files changed, 839 insertions(+), 44 deletions(-) create mode 100644 proj4/src/main/Proj4WKTQuestions.md create mode 100644 proj4/src/main/scala/geotrellis/proj4/io/wkt/WKTParser.scala create mode 100644 proj4/src/main/scala/geotrellis/proj4/io/wkt/WktCS.scala create mode 100644 proj4/src/test/scala/geotrellis/proj4/io/wkt/WKTParserTest.scala diff --git a/proj4/build.sbt b/proj4/build.sbt index f7f30b3ec1..380ef28b58 100644 --- a/proj4/build.sbt +++ b/proj4/build.sbt @@ -5,6 +5,7 @@ name := "geotrellis-proj4" libraryDependencies ++= Seq( openCSV, + parserCombinators, scalatest % "test", scalacheck % "test") diff --git a/proj4/src/main/Proj4WKTQuestions.md b/proj4/src/main/Proj4WKTQuestions.md new file mode 100644 index 0000000000..3d7bc8a898 --- /dev/null +++ b/proj4/src/main/Proj4WKTQuestions.md @@ -0,0 +1,11 @@ +# Questions During the Parsing of the EPSG.properties file + +[WKT format](http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html) + +1. 61766413 is a GEOGCS but has three axis rather than twin axis +2. Documentation for WKT says the directions are NORTH | SOUTH | EAST | WEST | UP | DOWN | OTHER + In epsg.properties there are the following WKTs with + AXIS["Geocentric X", GEOCENTRIC_X] + AXIS["Plant East", NORTH_EAST] + AXIS["Plant North", NORTH_WEST] +3. At line 5591 of epsg.properties removed two lines of comments diff --git a/proj4/src/main/resources/geotrellis/proj4/wkt/epsg.properties b/proj4/src/main/resources/geotrellis/proj4/wkt/epsg.properties index da81604d5f..ec7f107a47 100644 --- a/proj4/src/main/resources/geotrellis/proj4/wkt/epsg.properties +++ b/proj4/src/main/resources/geotrellis/proj4/wkt/epsg.properties @@ -1754,8 +1754,6 @@ 26972=PROJCS["NAD83 / Illinois West", GEOGCS["NAD83", DATUM["North American Datum 1983", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6269"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4269"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -90.16666666666667], PARAMETER["latitude_of_origin", 36.666666666666664], PARAMETER["scale_factor", 0.999941177], PARAMETER["false_easting", 700000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","26972"]] 26971=PROJCS["NAD83 / Illinois East", GEOGCS["NAD83", DATUM["North American Datum 1983", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6269"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4269"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -88.33333333333333], PARAMETER["latitude_of_origin", 36.666666666666664], PARAMETER["scale_factor", 0.999975], PARAMETER["false_easting", 300000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","26971"]] 26970=PROJCS["NAD83 / Idaho West", GEOGCS["NAD83", DATUM["North American Datum 1983", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6269"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4269"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -115.75], PARAMETER["latitude_of_origin", 41.666666666666664], PARAMETER["scale_factor", 0.999933333], PARAMETER["false_easting", 800000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","26970"]] -TEST2=GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH], AUTHORITY["EPSG","TEST2"]] -TEST1=GEOGCS["ED50", DATUM["European Datum 1950", SPHEROID["International 1924", 6378388.0, 297.0, AUTHORITY["EPSG","7022"]], TOWGS84[-116.641, -56.931, -110.559, 0.893, 0.921, -0.917, -3.52]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH], AUTHORITY["EPSG","TEST1"]] 26969=PROJCS["NAD83 / Idaho Central", GEOGCS["NAD83", DATUM["North American Datum 1983", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6269"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4269"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -114.0], PARAMETER["latitude_of_origin", 41.666666666666664], PARAMETER["scale_factor", 0.999947368], PARAMETER["false_easting", 500000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","26969"]] 26968=PROJCS["NAD83 / Idaho East", GEOGCS["NAD83", DATUM["North American Datum 1983", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6269"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4269"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -112.16666666666667], PARAMETER["latitude_of_origin", 41.666666666666664], PARAMETER["scale_factor", 0.999947368], PARAMETER["false_easting", 200000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","26968"]] 26967=PROJCS["NAD83 / Georgia West", GEOGCS["NAD83", DATUM["North American Datum 1983", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6269"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4269"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -84.16666666666667], PARAMETER["latitude_of_origin", 30.0], PARAMETER["scale_factor", 0.9999], PARAMETER["false_easting", 700000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","26967"]] @@ -5588,8 +5586,6 @@ TEST1=GEOGCS["ED50", DATUM["European Datum 1950", SPHEROID["International 1924", 3601=PROJCS["NAD83(NSRS2007) / Missouri Central", GEOGCS["NAD83(NSRS2007)", DATUM["NAD83 (National Spatial Reference System 2007)", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6759"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4759"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -92.5], PARAMETER["latitude_of_origin", 35.833333333333336], PARAMETER["scale_factor", 0.999933333], PARAMETER["false_easting", 500000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","3601"]] 3600=PROJCS["NAD83(NSRS2007) / Mississippi West (ftUS)", GEOGCS["NAD83(NSRS2007)", DATUM["NAD83 (National Spatial Reference System 2007)", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6759"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4759"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", -90.33333333333333], PARAMETER["latitude_of_origin", 29.5], PARAMETER["scale_factor", 0.99995], PARAMETER["false_easting", 2296583.333], PARAMETER["false_northing", 0.0], UNIT["foot_survey_us", 0.30480060960121924], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","3600"]] 62836405=GEOGCS["GDA94 (deg)", DATUM["Geocentric Datum of Australia 1994", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6283"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","62836405"]] -#Extra Definitions Supplied from Community -#Tue Jan 13 07:44:38 MST 2015 23433=PROJCS["Garoua / UTM zone 33N",GEOGCS["Garoua",DATUM["Garoua",SPHEROID["Clarke 1880 (IGN)",6378249.2,293.4660212936269,AUTHORITY["EPSG","7011"]],AUTHORITY["EPSG","6234"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9108"]],AUTHORITY["EPSG","4234"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",15],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","23433"]] 22832=PROJCS["Douala / UTM zone 32N",GEOGCS["Douala",DATUM["Douala",SPHEROID["Clarke 1880 (IGN)",6378249.2,293.4660212936269,AUTHORITY["EPSG","7011"]],AUTHORITY["EPSG","6228"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9108"]],AUTHORITY["EPSG","4228"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",9],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","22832"]] 2982=PROJCS["IGN72 Grand Terre / UTM zone 58S",GEOGCS["IGN72 Grand Terre",DATUM["IGN72_Grande_Terre",SPHEROID["International 1924",6378388,297,AUTHORITY["EPSG","7022"]],AUTHORITY["EPSG","6634"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9108"]],AUTHORITY["EPSG","4634"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",165],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",10000000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","2982"]] @@ -5605,7 +5601,7 @@ TEST1=GEOGCS["ED50", DATUM["European Datum 1950", SPHEROID["International 1924", 42304=PROJCS["NAD83 / NRCan LCC Canada",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS_1980",6378137,298.257222101],TOWGS84[0,0,0]],PRIMEM["Greenwich",0],UNIT["Decimal_Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["central_meridian",-95.0],PARAMETER["latitude_of_origin",49.0],PARAMETER["standard_parallel_1",49.0],PARAMETER["standard_parallel_2",77.0],PARAMETER["false_easting",0.0],PARAMETER["false_northing",0.0],UNIT["Meter",1],AUTHORITY["EPSG","42304"]] 42303=PROJCS["NAD83 / Albers NorthAm",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS_1980",6378137,298.257222101],TOWGS84[0,0,0]],PRIMEM["Greenwich",0],UNIT["Decimal_Degree",0.0174532925199433]],PROJECTION["Albers_conic_equal_area"],PARAMETER["central_meridian",-96.0],PARAMETER["latitude_of_origin",23],PARAMETER["standard_parallel_1",29.5],PARAMETER["standard_parallel_2",45.5],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],AUTHORITY["EPSG","42303"]] 42302=PROJCS["JapanOrtho.09 09",GEOGCS["Lon/Lat.Tokyo Datum",DATUM["Tokyo Datum",SPHEROID["anon",6377397.155,299.15281310608]],PRIMEM["Greenwich",0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["Central_Meridian",139.833333333333],PARAMETER["False_Easting",0],PARAMETER["False_Northing",0],PARAMETER["Latitude_of_Origin",36],PARAMETER["Scale_Factor",0.9999],UNIT["Meter",1],AUTHORITY["EPSG","42302"]] -42301=PROJCS["NAD27 / Polar Stereographic / CM\=-98",GEOGCS["NAD27",DATUM["North_American_Datum_1927",SPHEROID["Clarke 1866",6378206.4,294.978698213901],TOWGS84[-9,151,185]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Stereographic"],PARAMETER["latitude_of_origin",90],PARAMETER["central_meridian",-98.0],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],AUTHORITY["EPSG","42301"]] +42301=PROJCS["NAD27 / Polar Stereographic / CM=-98",GEOGCS["NAD27",DATUM["North_American_Datum_1927",SPHEROID["Clarke 1866",6378206.4,294.978698213901],TOWGS84[-9,151,185]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Stereographic"],PARAMETER["latitude_of_origin",90],PARAMETER["central_meridian",-98.0],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],AUTHORITY["EPSG","42301"]] 22700=PROJCS["Deir ez Zor / Levant Zone",GEOGCS["Deir ez Zor",DATUM["Deir_ez_Zor",SPHEROID["Clarke 1880 (IGN)",6378249.2,293.4660212936269,AUTHORITY["EPSG","7011"]],AUTHORITY["EPSG","6227"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4227"]],PROJECTION["Lambert_Conformal_Conic_1SP"],PARAMETER["latitude_of_origin",34.65],PARAMETER["central_meridian",37.35],PARAMETER["scale_factor",0.9996256],PARAMETER["false_easting",300000],PARAMETER["false_northing",300000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AUTHORITY["EPSG","22700"]] 104305=GEOGCS["GCS_Voirol_Unifie_1960_Degree",DATUM["D_Voirol_Unifie_1960",SPHEROID["Clarke_1880_RGS",6378249.145,293.465]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["ESRI","104305"]] 104304=GEOGCS["GCS_Voirol_1875_Degree",DATUM["D_Voirol_1875",SPHEROID["Clarke_1880_IGN",6378249.2,293.46602]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295],AUTHORITY["ESRI","104304"]] diff --git a/proj4/src/main/scala/geotrellis/proj4/io/wkt/WKT.scala b/proj4/src/main/scala/geotrellis/proj4/io/wkt/WKT.scala index 08f3f9dc9e..89c12ca649 100644 --- a/proj4/src/main/scala/geotrellis/proj4/io/wkt/WKT.scala +++ b/proj4/src/main/scala/geotrellis/proj4/io/wkt/WKT.scala @@ -21,29 +21,59 @@ import org.osgeo.proj4j.NotFoundException import scala.io.Source -/** - * @author Manuri Perera - */ object WKT { - private lazy val epsgcodetowktmap = new Memoize[String, String](retrieveWKTStringFromFile) - private lazy val wkttoepsgcodemap = new Memoize[String, String](retrieveEpsgCodeFromFile) private val wktResourcePath = "/geotrellis/proj4/wkt/epsg.properties" + lazy val parsed: Map[Int, WktCS] = records.mapValues(WKTParser.apply) + lazy val projections: Set[WktCS] = parsed.values.toSet + lazy val records: Map[Int, String] = parseWktEpsgResource + + def parseWktEpsgResource(): Map[Int, String] = { + //read input from epsg.properties file + WKT.withWktFile { lines => + println(lines) + val iter = + for (line <- lines) yield { + //split the line for parsing the wkt, aka remove code infront + val firstEquals = line.indexOf("=") + val code = line.substring(0, firstEquals).toInt + val wktString = line.substring(firstEquals + 1) + code -> wktString + } + iter.toMap + } + } + + def contains(input: WktCS): Boolean = { + projections contains input + } + + def getEpsgCodeOption(input: String): Option[Int] = { + val wktParsed = WKTParser(input) + parsed.find{ + case (epsgCode, wkt) => wkt == wktParsed + }.map(_._1) + } + + def getEpsgStringOption(input: Int): Option[String] = { + records.get(input).map(_.toString) + } + /** * Returns the WKT representation given an EPSG code in the format EPSG:[number] * @param code * @return */ - def fromEpsgCode(code: Int): String = epsgcodetowktmap(code.toString) + def fromEpsgCode(code: Int): String = getEpsgStringOption(code).get /** * Returns the numeric code of a WKT string given the authority * @param wktString * @return */ - def getEpsgCode(wktString: String) = wkttoepsgcodemap(wktString) + def getEpsgCode(wktString: String): String = s"EPSG:${getEpsgCodeOption(wktString).get}" - private def withWktFile[T](f: Iterator[String] => T) = { + def withWktFile[T](f: Iterator[String] => T) = { val stream = getClass.getResourceAsStream(wktResourcePath) try { f(Source.fromInputStream(stream).getLines()) @@ -52,35 +82,4 @@ object WKT { } } - /** - * Returns the WKT string for the passed EPSG code - * @param code - * @return - */ - private def retrieveWKTStringFromFile(code: String): String = - withWktFile { lines => - lines.find(_.split("=")(0) == code) match { - case Some(string) => - val array = string.split("=") - array(1) - case None => - throw new NotFoundException(s"Unable to find WKT representation of EPSG:$code") - } - } - - /** - * Returns the EPSG code for the passed WKT string - * @param wktString - * @return - */ - private def retrieveEpsgCodeFromFile(wktString: String): String = - withWktFile { lines => - lines.find(_.split("=")(1) == wktString) match { - case Some(string) => - val array = string.split("=") - s"EPSG:${array(0)}" - case None => - throw new NotFoundException(s"Unable to find the EPSG code of $wktString") - } - } } diff --git a/proj4/src/main/scala/geotrellis/proj4/io/wkt/WKTParser.scala b/proj4/src/main/scala/geotrellis/proj4/io/wkt/WKTParser.scala new file mode 100644 index 0000000000..58684b21d9 --- /dev/null +++ b/proj4/src/main/scala/geotrellis/proj4/io/wkt/WKTParser.scala @@ -0,0 +1,115 @@ +package geotrellis.proj4.io.wkt + +import scala.util.parsing.combinator.RegexParsers + +object WKTParser extends RegexParsers { + + override def skipWhitespace: Boolean = false + + def symbol: Parser[String] = """[A-Za-z0-9_]+""".r + + def string: Parser[String] = "\"" ~> """[A-Za-z=()/+ 0-9-&',.*?\_]+""".r <~ "\"" + + def double: Parser[Double] =("""[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?""".r | """[-+]?[0-9]*\.?[0-9]+""".r) map (_.toDouble) + + def int: Parser[Int] = """[-+]?[0-9]+""".r map (_.toInt) + + def value: Parser[Any] = string | double | int + + def comma: Parser[Any] = ("," ~ " ".?) map { + case x ~ _ => None + } + + def parameter: Parser[Parameter] = """PARAMETER[""" ~ string ~ comma ~ double ~ """]""" map { + case _ ~ name ~ _ ~ value ~ _=> new Parameter(name, value) + } + + def authority: Parser[Authority] = """AUTHORITY[""" ~ string ~ comma ~ string ~ """]""" map { + case _ ~ x ~ _~ y ~ _ => new Authority(x, y) + } + + def spheroid: Parser[Spheroid] = """SPHEROID[""" ~ string ~ comma ~ (double | int) ~ comma ~ double ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ axis ~ _ ~ flattening ~ _ ~ authority ~ _ => new Spheroid(name, axis, flattening, authority) + } + + def toWgs: Parser[ToWgs84] = """TOWGS84[""" ~ (double <~ comma.?).* ~ """]""" map { + case _ ~ x ~ _ => new ToWgs84(x) + } + + def datum: Parser[Datum] = """DATUM[""" ~ string ~ comma ~ spheroid ~ comma.? ~ toWgs.? ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ spheroid ~_ ~ toWgs ~ _ ~ authority ~ _ => new Datum(name, spheroid, toWgs, authority) + } + + def primeM: Parser[PrimeM] = """PRIMEM[""" ~ string ~ comma ~ double ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ longitude ~ _ ~ authority ~ _ => new PrimeM(name, longitude, authority) + } + + def axis: Parser[Axis] = """AXIS[""" ~ string ~ comma ~ (string | symbol) ~ """]""" map { + case _ ~ name ~ _ ~ direction ~ _ => new Axis(name, direction) + } + + def twinAxis: Parser[TwinAxis] = axis ~ comma ~ axis map { + case x ~ _ ~ y => new TwinAxis(x, y) + } + + def unitField: Parser[UnitField] = """UNIT[""" ~ string ~ comma ~ double ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ conversion ~ _ ~ authority ~ _ => new UnitField(name, conversion, authority) + } + + def vertDatum: Parser[VertDatum] = """VERT_DATUM[""" ~ string ~ comma ~ int ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ datumType ~ _ ~ authority ~ _ => new VertDatum(name, datumType, authority) + } + + def geogcs: Parser[GeogCS] = """GEOGCS[""" ~ string ~ comma ~ datum ~ comma ~ primeM ~ comma ~ unitField ~ comma.? ~ getAxisList.? ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ datum ~ _ ~ primeM ~_ ~ unitField ~ _~ axes ~ _ ~ auth ~ _ => new GeogCS(name, datum, primeM, unitField, axes, auth) + } + + def projection: Parser[Projection] = """PROJECTION[""" ~ string ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ authority ~ _ => new Projection(name, authority) + } + + def parameterList: Parser[List[Parameter]] = ((parameter ~ comma.?)*) ^^ (_.map(_._1)) + + def projcs: Parser[ProjCS] = """PROJCS[""" ~ string ~ comma ~ geogcs ~ comma ~ projection ~ comma.? ~ parameterList.? ~ comma.? ~ unitField ~ comma.? ~ twinAxis.? ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ geogcs ~ _ ~ projection ~ _ ~ params ~ _ ~ unitField ~ _ ~ twin ~ _ ~ authority ~ _ => new ProjCS(name, geogcs, projection, params, unitField, twin, authority) + } + + def vertcs: Parser[VertCS] = """VERT_CS[""" ~ string ~ comma ~ vertDatum ~ comma ~ unitField ~ comma.? ~ axis.? ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ vertDatum ~ _ ~ unitField ~ _ ~ axis ~ _ ~ authority ~ _ => new VertCS(name, vertDatum, unitField, axis, authority) + } + + def localDatum: Parser[LocalDatum] = """LOCAL_DATUM[""" ~ string ~ comma ~ int ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ datumType ~ _ ~ authority ~ _ => new LocalDatum(name, datumType, authority) + } + + def getAxisList: Parser[List[Axis]] = ((axis ~ comma.?)+)^^ (_.map(_._1)) + + def localcs: Parser[LocalCS] = """LOCAL_CS[""" ~ string ~ comma ~ localDatum ~ comma ~ unitField ~ comma ~ getAxisList ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ localDatum ~_ ~ unitField ~ _ ~ axisList ~ _ ~ authority ~ _ => new LocalCS(name, localDatum, unitField, axisList, authority) + } + + def geoccs: Parser[GeocCS] = """GEOCCS[""" ~ string ~ comma ~ datum ~ comma ~ primeM ~ comma ~ unitField ~ comma.? ~ getAxisList.? ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ datum ~ _ ~ primeM ~ _ ~ unitField ~ _ ~ getAxisList ~ _ ~ auth ~ _ => new GeocCS(name, datum, primeM, unitField, getAxisList, auth) + } + + def coordinateSys: Parser[Any] = geogcs | geoccs | projcs | vertcs | compdcs | localcs + + def compdcs: Parser[CompDCS] = """COMPD_CS[""" ~ string ~ comma ~ coordinateSys ~ comma ~ coordinateSys ~ comma.? ~ authority.? ~ """]""" map { + case _ ~ name ~ _ ~ head ~ _ ~ tail ~ _ ~ auth ~ _ => new CompDCS(name, head, tail, auth) + } + + def wktCS: Parser[WktCS] = localcs | projcs | geogcs | geoccs | compdcs | vertcs + + def apply(wktString: String) : WktCS = { + parseAll(wktCS, wktString) match { + case Success(wktObject, _) => + wktObject + case Failure(msg, tail) => + throw new IllegalArgumentException(msg) + case Error(msg, _) => { + throw new IllegalArgumentException(msg) + } + } + } + +} \ No newline at end of file diff --git a/proj4/src/main/scala/geotrellis/proj4/io/wkt/WktCS.scala b/proj4/src/main/scala/geotrellis/proj4/io/wkt/WktCS.scala new file mode 100644 index 0000000000..d32fd082c3 --- /dev/null +++ b/proj4/src/main/scala/geotrellis/proj4/io/wkt/WktCS.scala @@ -0,0 +1,39 @@ +package geotrellis.proj4.io.wkt + +sealed trait WktCS + +case class Authority(name: String, code: String) + +case class ToWgs84(values:List[Double]) + +case class Parameter(name: String, value: Number) + +case class Axis(name: String, direction: String) + +case class TwinAxis(first: Axis, second: Axis) + +case class Spheroid(name: String, semiMajorAxis: AnyVal, flatteningInverse: Double, authority: Option[Authority]) + +case class Datum(name: String, spheroid: Spheroid, towsg: Option[ToWgs84], authority: Option[Authority]) + +case class UnitField(name: String, conversionFact: Number, authority: Option[Authority]) + +case class PrimeM(name: String, longitude: Double, authority: Option[Authority]) + +case class VertDatum(name: String, datumType: Number, authority: Option[Authority]) + +case class LocalDatum(name: String, datumType: Number, authority: Option[Authority]) + +case class Projection(name: String, authority: Option[Authority]) + +case class GeogCS(name: String, datum: Datum, primeM: PrimeM, angularUnit: UnitField, axes: Option[List[Axis]], authority: Option[Authority]) extends WktCS + +case class ProjCS(name: String, geogcs: GeogCS, projection: Projection, params: Option[List[Parameter]], linearUnit: UnitField, twinAxis: Option[TwinAxis], authority: Option[Authority]) extends WktCS + +case class VertCS(name: String, vertDatum: VertDatum, unit: UnitField, axis: Option[Axis], authority: Option[Authority]) extends WktCS + +case class LocalCS(name: String, localDatum: LocalDatum, unit: UnitField, axisList: List[Axis], authority: Option[Authority]) extends WktCS + +case class GeocCS(name: String, datum: Datum, primeM: PrimeM, unit: UnitField, axis: Option[List[Axis]], authority: Option[Authority]) extends WktCS + +case class CompDCS(name: String, head: Any, tail: Any, authority: Option[Authority]) extends WktCS \ No newline at end of file diff --git a/proj4/src/test/scala/geotrellis/proj4/io/wkt/WKTParserTest.scala b/proj4/src/test/scala/geotrellis/proj4/io/wkt/WKTParserTest.scala new file mode 100644 index 0000000000..52f8f11d95 --- /dev/null +++ b/proj4/src/test/scala/geotrellis/proj4/io/wkt/WKTParserTest.scala @@ -0,0 +1,632 @@ +package geotrellis.proj4.io.wkt +import org.scalatest.FunSpec + +class WKTParserTest extends FunSpec { + + it("Should parse a simple string") { + import WKTParser._ + val expected = "EPSG" + parseAll(string, """"EPSG"""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a complex string") { + import WKTParser._ + val expected = "Barbados 1938 / Barbados National Grid" + parseAll(string, """"Barbados 1938 / Barbados National Grid"""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a complex string with parens") { + import WKTParser._ + val expected = "RGR92 (3D deg)" + parseAll(string, """"RGR92 (3D deg)"""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a comma") { + import WKTParser._ + val expected = None + parseAll(comma, """,""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a space and a comma") { + import WKTParser._ + val expected = None + parseAll(comma, """, """) match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a negative double") { + import WKTParser._ + val expected = -220.3 + parseAll(double, "-220.3") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse int") { + import WKTParser._ + val expected = 12 + parseAll(int, "12") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a negative int") { + import WKTParser._ + val expected = -12 + parseAll(int, "-12") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a value that is an int") { + import WKTParser._ + val expected = 12 + parseAll(value, "12") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a value that is a double") { + import WKTParser._ + val expected = 12.123 + parseAll(value, "12.123") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a value that is a simple string") { + import WKTParser._ + val expected = "helloWorld" + parseAll(value, """"helloWorld"""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should parse a value that is a complex string") { + import WKTParser._ + val expected = "Barbados 1938 / Barbados National Grid" + parseAll(value, """"Barbados 1938 / Barbados National Grid"""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an Authority object") { + import WKTParser._ + val expected = Authority("EPSG", "7019") + parseAll(authority, """AUTHORITY["EPSG","7019"]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an Spheroid object that has an authority") { + import WKTParser._ + val auth = Authority("EPSG", "7019") + val expected = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(auth)) + parseAll(spheroid, """SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an Spheroid object that has no authority") { + import WKTParser._ + val expected = new Spheroid("GRS 1980", 6378137.0, 298.257222101, None) + parseAll(spheroid, """SPHEROID["GRS 1980", 6378137.0, 298.257222101]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an ToWGS84 object") { + import WKTParser._ + val expected = new ToWgs84(List(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + parseAll(toWgs, """TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an Datum object with toWgs84 and authority") { + import WKTParser._ + val auth = new Authority("EPSG", "7019") + val spher = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(auth)) + val authDat = new Authority("EPSG", "6140") + val toWgs84 = new ToWgs84(List(-0.991, 1.9072, 0.5129, 0.0257899075194932, -0.009650098960270402, -0.011659943232342112, 0.0)) + val expected = new Datum("NAD83 Canadian Spatial Reference System", spher, Some(toWgs84), Some(authDat)) + parseAll(datum, """DATUM["NAD83 Canadian Spatial Reference System", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[-0.991, 1.9072, 0.5129, 0.0257899075194932, -0.009650098960270402, -0.011659943232342112, 0.0], AUTHORITY["EPSG","6140"]]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an Datum object without toWgs84 and with authority") { + import WKTParser._ + val auth = new Authority("EPSG", "7019") + val spher = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(auth)) + val authDat = new Authority("EPSG", "6140") + val expected = new Datum("NAD83 Canadian Spatial Reference System", spher, None, Some(authDat)) + parseAll(datum, """DATUM["NAD83 Canadian Spatial Reference System", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], AUTHORITY["EPSG","6140"]]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an Datum object with toWgs84 and without authority") { + import WKTParser._ + val auth = new Authority("EPSG", "7019") + val spher = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(auth)) + val toWgs84 = new ToWgs84(List(-0.991, 1.9072, 0.5129, 0.0257899075194932, -0.009650098960270402, -0.011659943232342112, 0.0)) + val expected = new Datum("NAD83 Canadian Spatial Reference System", spher, Some(toWgs84), None) + parseAll(datum, """DATUM["NAD83 Canadian Spatial Reference System", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[-0.991, 1.9072, 0.5129, 0.0257899075194932, -0.009650098960270402, -0.011659943232342112, 0.0]]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an PrimeM object with authority") { + import WKTParser._ + val auth = new Authority("EPSG", "8901") + val expected = new PrimeM("Greenwich", 0.0, Some(auth)) + parseAll(primeM, """PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return an PrimeM object without authority") { + import WKTParser._ + val auth = new Authority("EPSG", "8901") + val expected = new PrimeM("Greenwich", 0.0, None) + parseAll(primeM, """PRIMEM["Greenwich", 0.0]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return TwinAxis object") { + import WKTParser._ + val first = new Axis("Geodetic longitude", "EAST") + val second = new Axis("Geodetic latitude", "NORTH") + val expected = new TwinAxis(first, second) + parseAll(twinAxis, """AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return UnitField object") { + import WKTParser._ + val expected = new UnitField("degree", 0.017453292519943295, None) + parseAll(unitField, """UNIT["degree", 0.017453292519943295]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return Geogcs object") { + import WKTParser._ + val spherAuth = new Authority("EPSG", "7019") + val spher = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(spherAuth)) + val toWGS = new ToWgs84(List(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + val datumAuth = new Authority("EPSG", "6176") + val datum = new Datum("Australian Antarctic Datum 1998", spher, Some(toWGS), Some(datumAuth)) + val primeMAuth = new Authority("EPSG", "8901") + val primeM = new PrimeM("Greenwich", 0.0, Some(primeMAuth)) + val auth = new Authority("EPSG", "61766413") + val unitField = new UnitField("degree", 0.017453292519943295, None) + val axisOne = new Axis("Geodetic longitude", "EAST") + val axisTwo = new Axis("Geodetic latitude", "NORTH") + val expected = new GeogCS("Australian Antarctic (3D deg)", datum, primeM, unitField, Some(List(axisOne, axisTwo)), Some(auth)) + val geo = """GEOGCS["Australian Antarctic (3D deg)", DATUM["Australian Antarctic Datum 1998", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6176"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG", "8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","61766413"]]""" + parseAll(geogcs, geo) match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return Projection object") { + import WKTParser._ + val auth = new Authority("EPSG", "9802") + val expected = new Projection("Lambert_Conformal_Conic_2SP", Some(auth)) + parseAll(projection, """PROJECTION["Lambert_Conformal_Conic_2SP", AUTHORITY["EPSG","9802"]]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return Parameter object") { + import WKTParser._ + val expected = new Parameter("central_meridian", 3.0) + parseAll(parameter, """PARAMETER["central_meridian", 3.0]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return a list of Parameter objects") { + import WKTParser._ + val param1 = new Parameter("central_meridian", 3.0) + val param2 = new Parameter("latitude_of_origin", 42.0) + val param3 = new Parameter("standard_parallel_1", 42.75) + val param4 = new Parameter("false_easting", 1700000.0) + val expected = List(param1, param2, param3, param4) + parseAll(parameterList, """PARAMETER["central_meridian", 3.0], PARAMETER["latitude_of_origin", 42.0], PARAMETER["standard_parallel_1", 42.75], PARAMETER["false_easting", 1700000.0]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return a Projcs objects") { + import WKTParser._ + val toWgs84 = new ToWgs84(List(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + val spherAuth = new Authority("EPSG","7019") + val datumAuth = new Authority("EPSG","6171") + val geogcsAuth = new Authority("EPSG","4171") + val projectionAuth = new Authority("EPSG","9802") + val projAuth = new Authority("EPSG","3942") + val spheroid = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(spherAuth)) + val datum = new Datum("Reseau Geodesique Francais 1993", spheroid, Some(toWgs84), Some(datumAuth)) + val primeMAuth = new Authority("EPSG","8901") + val primeM = new PrimeM("Greenwich", 0.0, Some(primeMAuth)) + val geogcsUnit = new UnitField("degree", 0.017453292519943295, None) + val axisFirst = new Axis("Geodetic longitude", "EAST") + val axisSecond = new Axis("Geodetic latitude", "NORTH") + val geogcs = new GeogCS("RGF93", datum, primeM, geogcsUnit, Some(List(axisFirst, axisSecond)), Some(geogcsAuth)) + val projection = new Projection("Lambert_Conformal_Conic_2SP", Some(projectionAuth)) + val param1 = new Parameter("central_meridian", 3.0) + val param2 = new Parameter("latitude_of_origin", 42.0) + val param3 = new Parameter("standard_parallel_1", 42.75) + val param4 = new Parameter("false_easting", 1700000.0) + val param5 = new Parameter("false_northing", 1200000.0) + val param6 = new Parameter("scale_factor", 1.0) + val param7 = new Parameter("standard_parallel_2", 41.25) + val unitField = new UnitField("m", 1.0, None) + val axisOne = new Axis("Easting", "EAST") + val axisTwo = new Axis("Northing", "NORTH") + val twins = new TwinAxis(axisOne, axisTwo) + val paramsList = List(param1, param2, param3, param4, param5, param6, param7) + val expected = new ProjCS("RGF93 / CC42", geogcs, projection, Some(paramsList), unitField, Some(twins), Some(projAuth)) + val projcsString = """PROJCS["RGF93 / CC42", GEOGCS["RGF93", DATUM["Reseau Geodesique Francais 1993", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6171"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4171"]], PROJECTION["Lambert_Conformal_Conic_2SP", AUTHORITY["EPSG","9802"]], PARAMETER["central_meridian", 3.0], PARAMETER["latitude_of_origin", 42.0], PARAMETER["standard_parallel_1", 42.75], PARAMETER["false_easting", 1700000.0], PARAMETER["false_northing", 1200000.0], PARAMETER["scale_factor", 1.0], PARAMETER["standard_parallel_2", 41.25], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","3942"]]""" + parseAll(projcs, projcsString) match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return VertCS object") { + import WKTParser._ + val vertAuth = new Authority("EPSG","5621") + val datumAuth = new Authority("EPSG","5215") + val vertDatum = new VertDatum("European Vertical Reference Frame 2007", 2005, Some(datumAuth)) + val axis = new Axis("Gravity-related height", "UP") + val unitField = new UnitField("m", 1.0, None) + val expected = new VertCS("EVRF2007 height", vertDatum, unitField, Some(axis), Some(vertAuth)) + parseAll(vertcs, """VERT_CS["EVRF2007 height", VERT_DATUM["European Vertical Reference Frame 2007", 2005, AUTHORITY["EPSG","5215"]], UNIT["m", 1.0], AXIS["Gravity-related height", UP], AUTHORITY["EPSG","5621"]]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return a list of Axis objects") { + import WKTParser._ + val axis1 = new Axis("x", "EAST") + val axis2 = new Axis("y", "NORTH") + val expected = List(axis1, axis2) + parseAll(getAxisList, """AXIS["x", EAST], AXIS["y", NORTH]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return a LocalDatum object no authority") { + import WKTParser._ + val expected = new LocalDatum("Unknown", 0, None) + parseAll(localDatum, """LOCAL_DATUM["Unknown", 0]""") match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return a LocalCS object") { + import WKTParser._ + val datumAuth = new Authority("EPSG","9314") + val localDatum = new LocalDatum("Tombak LNG plant", 0, Some(datumAuth)) + val axis1 = new Axis("Plant East", "EAST") + val axis2 = new Axis("Plant North", "WEST") + val axisList = List(axis1, axis2) + val localAuth = new Authority("EPSG","5817") + val unitField = new UnitField("m", 1.0, None) + val expected = new LocalCS("Tombak LNG plant", localDatum, unitField, axisList, Some(localAuth)) + val localCSString = """LOCAL_CS["Tombak LNG plant", LOCAL_DATUM["Tombak LNG plant", 0, AUTHORITY["EPSG","9314"]], UNIT["m", 1.0], AXIS["Plant East", EAST], AXIS["Plant North", WEST], AUTHORITY["EPSG","5817"]]""" + parseAll(localcs, localCSString) match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return a Geoccs object") { + import WKTParser._ + val spherAuth = new Authority("EPSG","7019") + val spheroid = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(spherAuth)) + val toWgs84 = new ToWgs84(List(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + val datumAuth = new Authority("EPSG","1035") + val datum = new Datum("Red Geodesica de Canarias 1995", spheroid, Some(toWgs84), Some(datumAuth)) + var primeM = new PrimeM("Greenwich", 0.0, Some(new Authority("EPSG","8901"))) + val unitField = new UnitField("m", 1.0, None) + val axis1 = new Axis("Geocentric X", "GEOCENTRIC_X") + val axis2 = new Axis("Geocentric Y", "GEOCENTRIC_Y") + val axis3 = new Axis("Geocentric Z", "GEOCENTRIC_Z") + val auth = new Authority("EPSG","4079") + val expected = new GeocCS("REGCAN95", datum, primeM, unitField, Some(List(axis1, axis2, axis3)), Some(auth)) + val geoCCSString = """GEOCCS["REGCAN95", DATUM["Red Geodesica de Canarias 1995", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","1035"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["m", 1.0], AXIS["Geocentric X", GEOCENTRIC_X], AXIS["Geocentric Y", GEOCENTRIC_Y], AXIS["Geocentric Z", GEOCENTRIC_Z], AUTHORITY["EPSG","4079"]]""" + parseAll(geoccs, geoCCSString) match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + + it("Should return a Compdcs object") { + import WKTParser._ + val authGeogcs = new Authority("EPSG","6258") + val authSpher = new Authority("EPSG","7019") + val authPrimeM = new Authority("EPSG","8901") + val toWgs84 = new ToWgs84(List(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + val spher = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(authSpher)) + val datum = new Datum("European Terrestrial Reference System 1989", spher, Some(toWgs84), Some(authGeogcs)) + val primeM = new PrimeM("Greenwich", 0.0, Some(authPrimeM)) + val unitField = new UnitField("degree", 0.017453292519943295, None) + val axis1 = new Axis("Geodetic latitude", "NORTH") + val axis2 = new Axis("Geodetic longitude", "EAST") + val geogcs = new GeogCS("ETRS89", datum, primeM, unitField, Some(List(axis1, axis2)), Some(new Authority("EPSG","4258"))) + val projection = new Projection("Transverse_Mercator", Some(new Authority("EPSG","9807"))) + val param1 = new Parameter("central_meridian", 33.0) + val param2 = new Parameter("latitude_of_origin", 0.0) + val param3 = new Parameter("scale_factor", 0.9996) + val param4 = new Parameter("false_easting", 500000.0) + val param5 = new Parameter("false_northing", 0.0) + val paramsList = List(param1, param2, param3, param4, param5) + val axisProj1 = new Axis("Easting", "EAST") + val axisProj2 = new Axis("Northing", "NORTH") + val twinsProj = new TwinAxis(axisProj1, axisProj2) + val authProj = new Authority("EPSG","25836") + val projcs = new ProjCS("ETRS89 / UTM zone 36N", geogcs, projection, Some(paramsList), new UnitField("m", 1.0, None), Some(twinsProj), Some(authProj)) + val authGeoCCS = new Authority("EPSG","6176") + val vertCSAuth = new Authority("EPSG","5776") + val vertDatumAuth = new Authority("EPSG","5174") + val vertDatum = new VertDatum("Norway Normal Null 1954", 2005, Some(vertDatumAuth)) + val vertAxis = new Axis("Gravity-related height", "UP") + val vertUnit = new UnitField("m", 1.0, None) + val vertCS = new VertCS("NN54 height", vertDatum, vertUnit, Some(vertAxis), Some(vertCSAuth)) + val expected = new CompDCS("ETRS89 / UTM zone 36 + NN54 height", projcs, vertCS, Some(authGeoCCS)) + val geoCCSString = """COMPD_CS["ETRS89 / UTM zone 36 + NN54 height", PROJCS["ETRS89 / UTM zone 36N", GEOGCS["ETRS89", DATUM["European Terrestrial Reference System 1989", SPHEROID["GRS 1980", 6378137.0, 298.257222101, AUTHORITY["EPSG","7019"]], TOWGS84[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6258"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic latitude", NORTH], AXIS["Geodetic longitude", EAST], AUTHORITY["EPSG","4258"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", 33.0], PARAMETER["latitude_of_origin", 0.0], PARAMETER["scale_factor", 0.9996], PARAMETER["false_easting", 500000.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","25836"]], VERT_CS["NN54 height", VERT_DATUM["Norway Normal Null 1954", 2005, AUTHORITY["EPSG","5174"]], UNIT["m", 1.0], AXIS["Gravity-related height", UP], AUTHORITY["EPSG","5776"]], AUTHORITY["EPSG","6176"]]""" + parseAll(compdcs, geoCCSString) match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should return a Projcs object special one") { + import WKTParser._ + val authProjcs = new Authority("EPSG","22033") + val authSpher = new Authority("EPSG","7012") + val spher = new Spheroid("Clarke 1880 (RGS)", 6378249.145, 293.465, Some(authSpher)) + val toWgs84 = new ToWgs84(List(-50.9, -347.6, -231.0, 0.0, 0.0, 0.0, 0.0)) + val authDatum = new Authority("EPSG","6220") + val datum = new Datum("Camacupa", spher, Some(toWgs84), Some(authDatum)) + val authPrimeM = new Authority("EPSG","8901") + val primeM = new PrimeM("Greenwich", 0.0, Some(authPrimeM)) + val unitField = new UnitField("degree", 0.017453292519943295, None) + val axis1 = new Axis("Geodetic longitude", "EAST") + val axis2 = new Axis("Geodetic latitude", "NORTH") + val authGeogcs = new Authority("EPSG","4220") + val geogcs = new GeogCS("Camacupa", datum, primeM, unitField, Some(List(axis1, axis2)), Some(authGeogcs)) + val projection = new Projection("Transverse_Mercator", Some(new Authority("EPSG","9807"))) + val param1 = new Parameter("central_meridian", 15.0) + val param2 = new Parameter("latitude_of_origin", 0.0) + val param3 = new Parameter("scale_factor", 0.9996) + val param4 = new Parameter("false_easting", 500000.0) + val param5 = new Parameter("false_northing", 10000000.0) + val paramsList = List(param1, param2, param3, param4, param5) + val unitProj = new UnitField("m", 1.0, None) + val axisProj1 = new Axis("Easting", "EAST") + val axisProj2 = new Axis("Northing", "NORTH") + val expected = new ProjCS("Camacupa / UTM zone 33S", geogcs, projection, Some(paramsList), unitProj, Some(new TwinAxis(axisProj1, axisProj2)), Some(authProjcs)) + val projcsString = """PROJCS["Camacupa / UTM zone 33S", GEOGCS["Camacupa", DATUM["Camacupa", SPHEROID["Clarke 1880 (RGS)", 6378249.145, 293.465, AUTHORITY["EPSG","7012"]], TOWGS84[-50.9, -347.6, -231.0, 0.0, 0.0, 0.0, 0.0], AUTHORITY["EPSG","6220"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4220"]], PROJECTION["Transverse_Mercator", AUTHORITY["EPSG","9807"]], PARAMETER["central_meridian", 15.0], PARAMETER["latitude_of_origin", 0.0], PARAMETER["scale_factor", 0.9996], PARAMETER["false_easting", 500000.0], PARAMETER["false_northing", 10000000.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","22033"]]""" + parseAll(projcs, projcsString) match { + case Success(n, _) => + assert(n == expected) + case Failure(msg, _) => + info(msg) + fail() + } + } + + it("Should contain NAD27 / Polar Stereographic / CM=-98") { + import WKT._ + val datSpheroid = new Spheroid("Clarke 1866", 6378206.4, 294.978698213901, None) + val toWgs84 = new ToWgs84(List(-9, 151, 185)) + val datum = new Datum("North_American_Datum_1927", datSpheroid, Some(toWgs84), None) + val primeM = new PrimeM("Greenwich", 0, None) + val unitFieldGeo = new UnitField("degree", 0.0174532925199433, None) + val geogcs = new GeogCS("NAD27", datum, primeM, unitFieldGeo, None, None) + val projection = new Projection("Stereographic", None) + val param1 = new Parameter("latitude_of_origin", 90) + val param2 = new Parameter("central_meridian", -98.0) + val param3 = new Parameter("scale_factor", 0.9996) + val param4 = new Parameter("false_easting", 0) + val param5 = new Parameter("false_northing",0) + val unitField = new UnitField("Meter", 1, None) + val auth = new Authority("EPSG", "42301") + val expected = new ProjCS("NAD27 / Polar Stereographic / CM=-98", geogcs, projection, Some(List(param1, param2, param3, param4, param5)), unitField, None, Some(auth)) + assert(contains(expected)) + } + + it("Should return a contain the Geoccs object") { + import WKT._ + val spherAuth = new Authority("EPSG","7019") + val spheroid = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(spherAuth)) + val toWgs84 = new ToWgs84(List(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)) + val datumAuth = new Authority("EPSG","1035") + val datum = new Datum("Red Geodesica de Canarias 1995", spheroid, Some(toWgs84), Some(datumAuth)) + var primeM = new PrimeM("Greenwich", 0.0, Some(new Authority("EPSG","8901"))) + val unitField = new UnitField("m", 1.0, None) + val axis1 = new Axis("Geocentric X", "GEOCENTRIC_X") + val axis2 = new Axis("Geocentric Y", "GEOCENTRIC_Y") + val axis3 = new Axis("Geocentric Z", "GEOCENTRIC_Z") + val auth = new Authority("EPSG","4079") + val expected = new GeocCS("REGCAN95", datum, primeM, unitField, Some(List(axis1, axis2, axis3)), Some(auth)) + assert(contains(expected)) + } + + it("Should parse NAD83(CSRS98) / New Brunswick Stereo") { + import WKT._ + val spherAuth = new Authority("EPSG","7019") + val datumSpher = new Spheroid("GRS 1980", 6378137.0, 298.257222101, Some(spherAuth)) + val toWgs84 = new ToWgs84(List(0, 0, 0)) + val datumAuth = new Authority("EPSG","6140") + val geoDatum = new Datum("NAD83_Canadian_Spatial_Reference_System", datumSpher, Some(toWgs84), Some(datumAuth)) + val primeMAuth = new Authority("EPSG","8901") + val primeM = new PrimeM("Greenwich", 0, Some(primeMAuth)) + val unitAuth = new Authority("EPSG","9108") + val unitField = new UnitField("degree", 0.0174532925199433, Some(unitAuth)) + val geoAuth = new Authority("EPSG","4140") + val geogcs = new GeogCS("NAD83(CSRS98)", geoDatum, primeM, unitField, None, Some(geoAuth)) + val projection = new Projection("Oblique_Stereographic", None) + val param1 = new Parameter("latitude_of_origin", 46.5) + val param2 = new Parameter("central_meridian", -66.5) + val param3 = new Parameter("scale_factor", 0.999912) + val param4 = new Parameter("false_easting", 2500000.0) + val param5 = new Parameter("false_northing", 7500000.0) + val paramList = List(param1, param2, param3, param4, param5) + val unitProj = new UnitField("metre", 1.0, Some(new Authority("EPSG", "9001"))) + val auth = new Authority("EPSG", "2036") + val expected = new ProjCS("NAD83(CSRS98) / New Brunswick Stereo", geogcs, projection, Some(paramList), unitProj, None, Some(auth)) + assert(contains(expected)) + } + +} diff --git a/project/Dependencies.scala b/project/Dependencies.scala index cd59197e69..29c719831a 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -62,4 +62,6 @@ object Dependencies { val avro = "org.apache.avro" % "avro" % "1.8.1" val slickPG = "com.github.tminglei" %% "slick-pg" % "0.14.3" + + val parserCombinators = "org.scala-lang.modules" %% "scala-parser-combinators" % "1.0.4" } From caba9f620039692e1dbfddb9a906589c2c265698 Mon Sep 17 00:00:00 2001 From: miafg Date: Tue, 20 Dec 2016 13:36:44 -0500 Subject: [PATCH 2/2] removed file Signed-off-by: miafg --- proj4/src/main/Proj4WKTQuestions.md | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 proj4/src/main/Proj4WKTQuestions.md diff --git a/proj4/src/main/Proj4WKTQuestions.md b/proj4/src/main/Proj4WKTQuestions.md deleted file mode 100644 index 3d7bc8a898..0000000000 --- a/proj4/src/main/Proj4WKTQuestions.md +++ /dev/null @@ -1,11 +0,0 @@ -# Questions During the Parsing of the EPSG.properties file - -[WKT format](http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html) - -1. 61766413 is a GEOGCS but has three axis rather than twin axis -2. Documentation for WKT says the directions are NORTH | SOUTH | EAST | WEST | UP | DOWN | OTHER - In epsg.properties there are the following WKTs with - AXIS["Geocentric X", GEOCENTRIC_X] - AXIS["Plant East", NORTH_EAST] - AXIS["Plant North", NORTH_WEST] -3. At line 5591 of epsg.properties removed two lines of comments