Skip to content

Commit 39031c1

Browse files
committed
Refine CRS WKT parsing error message and test
Signed-off-by: Jason T. Brown <[email protected]>
1 parent 8b948fc commit 39031c1

File tree

2 files changed

+41
-3
lines changed

2 files changed

+41
-3
lines changed

core/src/main/scala/org/locationtech/rasterframes/model/LazyCRS.scala

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import org.locationtech.rasterframes.encoders.CatalystSerializer
2828
import org.locationtech.rasterframes.model.LazyCRS.EncodedCRS
2929

3030
class LazyCRS(val encoded: EncodedCRS) extends CRS {
31-
private lazy val delegate = LazyCRS.cache.get(encoded)
31+
private lazy val delegate: CRS = LazyCRS.cache.get(encoded)
3232
override def proj4jCrs: CoordinateReferenceSystem = delegate.proj4jCrs
3333
override def toProj4String: String =
3434
if (encoded.startsWith("+proj")) encoded
@@ -50,11 +50,15 @@ object LazyCRS {
5050
trait ValidatedCRS
5151
type EncodedCRS = String with ValidatedCRS
5252

53+
val wktKeywords = Seq("GEOGCS", "PROJCS", "GEOCCS")
54+
5355
@transient
5456
private lazy val mapper: PartialFunction[String, CRS] = {
5557
case e if e.toUpperCase().startsWith("EPSG") => CRS.fromName(e) //not case-sensitive
5658
case p if p.startsWith("+proj") => CRS.fromString(p) // case sensitive
57-
case w if w.toUpperCase().startsWith("GEOGCS") => CRS.fromWKT(w) //only case-sensitive inside double quotes
59+
case w if wktKeywords.exists{prefix
60+
w.toUpperCase().startsWith(prefix)
61+
} CRS.fromWKT(w) //only case-sensitive inside double quotes
5862
}
5963

6064
@transient
@@ -67,7 +71,7 @@ object LazyCRS {
6771
new LazyCRS(value.asInstanceOf[EncodedCRS])
6872
}
6973
else throw new IllegalArgumentException(
70-
"crs string must be either EPSG code, +proj string, or OGC WKT")
74+
s"CRS string must be either EPSG code, +proj string, or OGC WKT (WKT1). Argument value was ${if (value.length > 50) value.substring(0, 50) + "..." else value} ")
7175
}
7276

7377
implicit val crsSererializer: CatalystSerializer[LazyCRS] = CatalystSerializer.crsSerializer.asInstanceOf[CatalystSerializer[LazyCRS]]

core/src/test/scala/org/locationtech/rasterframes/model/LazyCRSSpec.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import org.scalatest._
2727
class LazyCRSSpec extends FunSpec with Matchers {
2828
val sinPrj = "+proj=sinu +lon_0=0 +x_0=0 +y_0=0 +a=6371007.181 +b=6371007.181 +units=m +no_defs"
2929
val llPrj = "epsg:4326"
30+
31+
3032
describe("LazyCRS") {
3133
it("should implement equals") {
3234
LazyCRS(WebMercator) should be(LazyCRS(WebMercator))
@@ -39,5 +41,37 @@ class LazyCRSSpec extends FunSpec with Matchers {
3941
LatLng should be(LazyCRS(llPrj))
4042
LatLng should be(LazyCRS(LatLng))
4143
}
44+
it("should interpret WKT1 GEOGCS correctly"){
45+
46+
// This is from geotrellis.proj4.io.wkt.WKT.fromEpsgCode(4326)
47+
// Note it has subtle differences from other WKT1 forms
48+
val wktWGS84 = "GEOGCS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", SPHEROID[\"WGS 84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7030\"]], AUTHORITY[\"EPSG\",\"6326\"]], PRIMEM[\"Greenwich\", 0.0, AUTHORITY[\"EPSG\",\"8901\"]], UNIT[\"degree\", 0.017453292519943295], AXIS[\"Geodetic longitude\", EAST], AXIS[\"Geodetic latitude\", NORTH], AUTHORITY[\"EPSG\",\"4326\"]]"
49+
50+
val crs = LazyCRS(wktWGS84)
51+
52+
crs.toProj4String should startWith("+proj=longlat")
53+
crs.toProj4String should include("+datum=WGS84")
54+
}
55+
56+
it("should interpret WKT1 PROJCS correctly") {
57+
58+
// Via geotrellis.proj4.io.wkt.WKT.fromEpsgCode
59+
val wktUtm17N = "PROJCS[\"WGS 84 / UTM zone 17N\", GEOGCS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", SPHEROID[\"WGS 84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7030\"]], AUTHORITY[\"EPSG\",\"6326\"]], PRIMEM[\"Greenwich\", 0.0, AUTHORITY[\"EPSG\",\"8901\"]], UNIT[\"degree\", 0.017453292519943295], AXIS[\"Geodetic longitude\", EAST], AXIS[\"Geodetic latitude\", NORTH], AUTHORITY[\"EPSG\",\"4326\"]], PROJECTION[\"Transverse_Mercator\", AUTHORITY[\"EPSG\",\"9807\"]], PARAMETER[\"central_meridian\", -81.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\",\"32617\"]]"
60+
61+
val utm17n = LazyCRS(wktUtm17N)
62+
utm17n.toProj4String should startWith("+proj=utm")
63+
utm17n.toProj4String should include("+zone=17")
64+
utm17n.toProj4String should include("+datum=WGS84")
65+
}
66+
67+
ignore("should interpret WKT GEOCCS correctly"){
68+
// geotrellis.proj4.io.wkt. WKT.fromEpsgCode(4978) gives this but
69+
// .... fails on trying to instantiate
70+
val wktWgsGeoccs = "GEOCCS[\"WGS 84\", DATUM[\"World Geodetic System 1984\", SPHEROID[\"WGS 84\", 6378137.0, 298.257223563, AUTHORITY[\"EPSG\",\"7030\"]], AUTHORITY[\"EPSG\",\"6326\"]], 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\",\"4978\"]]"
71+
72+
val crs = LazyCRS(wktWgsGeoccs)
73+
crs.toProj4String should startWith("+proj=geocent")
74+
crs.toProj4String should include("+datum=WGS84")
75+
}
4276
}
4377
}

0 commit comments

Comments
 (0)