Does anyone know of some Scala libraries for drawing maps of the globe (the Earth) or portions of the Earth. Funny thing, when I search for Scala maps I find it a lot about the map
method or Map
data types.
No experience in this area, but
- use “geo” as a search term instead of/in addition to “map”
- as usual: if nothing comes up for native Scala, look on the Java side instead
Found the following, which looks interesting. scala-shapefile
Investigating…
There seems to be some problem with something called ShouldMatchers
when I try to run the test cases…
I cloned the git repo and tried to run the tests. I immediately get the following errors the errors shown below (at the bottom). I then edited the build.sbt file to update the scala version from 2.10 to 2.12.8 and the scalatest version from 2.0.M5b to 3.0.5.
Now when I try to run the tests, it looks like there is some incompatible change regarding ShouldMatchers
. Perhaps that’s something that no longer exists in scala-test?
Error:(4, 8) object ShouldMatchers is not a member of package org.scalatest.matchers
import org.scalatest.matchers.ShouldMatchers
Any suggestions about how to fix this?
package geotrellis
import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers
import com.vividsolutions.jts.geom._
class ShapefileSpec extends FlatSpec with ShouldMatchers {
implicit val g: GeometryFactory = new GeometryFactory()
"Shapefile parser" should "parse a shapefile" in {
val p = shapefile.Parser("src/test/resources/UScounties.shp")
println(p.map(_.id))
}
}
Original compilation errors.
Error:scalac: Error: Error compiling the sbt component 'compiler-interface-2.10.0-52.0'
sbt.internal.inc.CompileFailed: Error compiling the sbt component 'compiler-interface-2.10.0-52.0'
at sbt.internal.inc.AnalyzingCompiler$.handleCompilationError$1(AnalyzingCompiler.scala:331)
at sbt.internal.inc.AnalyzingCompiler$.$anonfun$compileSources$4(AnalyzingCompiler.scala:346)
at sbt.internal.inc.AnalyzingCompiler$.$anonfun$compileSources$4$adapted(AnalyzingCompiler.scala:341)
at sbt.io.IO$.withTemporaryDirectory(IO.scala:376)
at sbt.io.IO$.withTemporaryDirectory(IO.scala:383)
at sbt.internal.inc.AnalyzingCompiler$.$anonfun$compileSources$2(AnalyzingCompiler.scala:341)
at sbt.internal.inc.AnalyzingCompiler$.$anonfun$compileSources$2$adapted(AnalyzingCompiler.scala:335)
at sbt.io.IO$.withTemporaryDirectory(IO.scala:376)
at sbt.io.IO$.withTemporaryDirectory(IO.scala:383)
at sbt.internal.inc.AnalyzingCompiler$.compileSources(AnalyzingCompiler.scala:335)
at org.jetbrains.jps.incremental.scala.local.CompilerFactoryImpl$.getOrCompileInterfaceJar(CompilerFactoryImpl.scala:113)
at org.jetbrains.jps.incremental.scala.local.CompilerFactoryImpl.$anonfun$getScalac$1(CompilerFactoryImpl.scala:49)
at scala.Option.map(Option.scala:146)
at org.jetbrains.jps.incremental.scala.local.CompilerFactoryImpl.getScalac(CompilerFactoryImpl.scala:47)
at org.jetbrains.jps.incremental.scala.local.CompilerFactoryImpl.createCompiler(CompilerFactoryImpl.scala:25)
at org.jetbrains.jps.incremental.scala.local.CachingFactory.$anonfun$createCompiler$3(CachingFactory.scala:24)
at org.jetbrains.jps.incremental.scala.local.Cache.$anonfun$getOrUpdate$2(Cache.scala:20)
at scala.Option.getOrElse(Option.scala:121)
at org.jetbrains.jps.incremental.scala.local.Cache.getOrUpdate(Cache.scala:19)
at org.jetbrains.jps.incremental.scala.local.CachingFactory.createCompiler(CachingFactory.scala:24)
at org.jetbrains.jps.incremental.scala.local.LocalServer.compile(LocalServer.scala:27)
at org.jetbrains.jps.incremental.scala.remote.Main$.make(Main.scala:89)
at org.jetbrains.jps.incremental.scala.remote.Main$.nailMain(Main.scala:35)
at org.jetbrains.jps.incremental.scala.remote.Main.nailMain(Main.scala)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.martiansoftware.nailgun.NGSession.run(NGSession.java:319)
Exactly. I’d recommend to forget about this project - too old/unmaintained, and it probably doesn’t cover what you’re looking for, anyway.
At first glance, GeoTools seems to be the go-to library for geospatial stuff on the JVM, and it comes with support for map rendering. There’s GeoTrellis for Scala, but it’s based on Spark, which would be a red flag for me in the context of a desktop app or library.
What I’m looking for is much simpler than GeoTools, although I can still check it out. What I’d like to be able to do is access boundary data for countries (and perhaps US states and counties) in latitude/longitude coordinates, and be able to plot them with something like ScalaFX or SwiftViz2. Later I want to make calculations based on latitude/longitude and colorize that into the drawn map.
This looks arduous. Sadly, GeoTools seems to be unapologetically “aimed at Java developers”. There are a bunch of getting started tutorials, but they are all for the Java programmer. It would be great to have a resource: All the Java you need to program in Scala: Scala for the non-Java-ite.
If all you need right now really is shapefile parsing, you could check if the GeoTrellis ShapeFileReader could be used in isolation.
I can sympathize, and coming from Java, I guess I tend to underestimate this hurdle.
The ability to draw from the Java library ecosystem is a huge benefit of Scala - but it comes with the downside that often there will be no native Scala solution where the existing Java coverage is “good enough”. So I guess at some point in time one just has to bite the bullet and learn to interpret at least Java API basics for Scala usage. Unfortunately I’m not aware of any decent “Java for Scalaists” tutorial. To get started, there’s some Java-to-Scala converters out there - IntelliJ IDEA comes with a builtin one, for example.
I think it’s not really Java per se, but its all the meta-java stuff.
What meta-java stuff? Java is notorious for not having enough meta, that’s one reason for Scala’s existence in the first place.
If you are alluding to the Maven deps…
<dependency>
<groupId>org.geotools</groupId>
<artifactId>gt-shapefile</artifactId>
<version>${geotools.version}</version>
</dependency>
directly translates to
libraryDependencies += "org.geotools" % "gt-shapefile" % "<whatever geotools version>"
in sbt.
Other than that, I don’t see any relevant meta stuff…?
Thanks for the maven translation. Another example is from http://docs.geotools.org/latest/userguide/tutorial/filter/query.html there seem to be a lot of these huge xml structures, something about making sure you have a certain structure in the pom.xml file. The same link has a huge set of imports. Can I copy java imports directly into Scala, or do I need to understand and convert them?
repositories
in a mvn POM corresponds to resolvers
in an sbt file. dependencies
: same as above.
Java import statements sans the semicolon are valid Scala import statements. You can also just paste Java snippets, including import sections, into a Scala source file in IntelliJ IDEA and it will offer to convert the code.
I will throw a comment here to avoid confusion that GeoTrellis is not Spark centric; Spark packages are separated out from the packages that can be used without Spark. And you’re all welcome into our gitter channel to get help with getting started.
It looks like in this case it is possible to use geotrellis-vector
package which provides thin wrappers over JTS (with some extra functionality around it) and GeoJSON parsers. It also makes sense to use geotrellis-shapefile
which contains ShapeFile reader wrapper, if you really need to deal with shapefiles.