%useLatestDescriptors %use lets-plot // Initialize Lets-Plot GeoTools extension. %use lets-plot-gt(gt="[23,)") LetsPlot.getInfo() @file:DependsOn("org.geotools:gt-shapefile:[23,)") @file:DependsOn("org.geotools:gt-cql:[23,)") import org.geotools.data.shapefile.ShapefileDataStoreFactory import org.geotools.data.simple.SimpleFeatureCollection import java.net.URL val factory = ShapefileDataStoreFactory() val worldFeatures : SimpleFeatureCollection = with("naturalearth_lowres") { val url = "https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/docs/examples/shp/${this}/${this}.shp" factory.createDataStore(URL(url)).featureSource.features } // Convert Feature Collection to SpatialDataset. // Use 10 decimals to encode floating point numbers (this is the default). val world = worldFeatures.toSpatialDataset(10) world["continent"]?.distinct() val voidTheme = theme(axis="blank", panelGrid="blank") // Use the parameter `map` in `geomPolygon()` to display Polygons / Multi-Polygons letsPlot() + geomPolygon(map = world, fill = "white", color = "gray") + ggsize(700, 400) + voidTheme letsPlot() + geomMap(map = world) + ggsize(700, 400) + voidTheme // When applying Mercator projection to the world map, Antarctica becomes disproportionally large so // in the future let's show only part of it above 85-th parallel south: val worldLimits = coordMap(ylim = -70 to 85) val cityFeatures : SimpleFeatureCollection = with("naturalearth_cities") { val url = "https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/docs/examples/shp/${this}/${this}.shp" factory.createDataStore(URL(url)).featureSource.features } // Use parameter `map` in `geomPoint()` to display Point shapes val cities = cityFeatures.toSpatialDataset(10) letsPlot() + geomMap(map = world) + geomPoint(map = cities, color = "red") + ggsize(800, 600) + voidTheme + worldLimits import org.geotools.filter.text.cql2.CQL // Obtain bounding box of South America and use it to set the limits. val southAm = worldFeatures.subCollection( CQL.toFilter("continent = 'South America'") ) val southAmBounds = southAm.bounds // Let's use slightly expanded boundind box. southAmBounds.expandBy(4.0) // Define limits to use later with city markers and labels. val southAmLimits = coordMap( xlim = southAmBounds.minX to southAmBounds.maxX, ylim = southAmBounds.minY to southAmBounds.maxY ) letsPlot() + geomMap(map = southAm.toSpatialDataset()) + geomRect(map = southAmBounds.toSpatialDataset(), alpha = 0, color = "#EFC623") // Add `text` layer and use the `data` parameter to pass `cities` SpartialDataset. // Also configure `tooltip` in the points layer to show the city name. letsPlot() + geomMap(map = southAm.toSpatialDataset(), fill="#e5f5e0") + geomPoint(data = cities, color = "red", size = 3, tooltips = layerTooltips().line("@name")) + geomText(data = cities, vjust = 1, position = positionNudge(y = -.5)) { label = "name" } + geomRect(map = southAmBounds.toSpatialDataset(), alpha = 0, color="#EFC623", size=16) + southAmLimits + ggsize(450, 691) + voidTheme // Create choropleth by mapping the `continent` variable to the `fill` aesthetic. letsPlot() + geomMap(data = world, color = "white") { fill = "continent" } + ggsize(900, 400) + voidTheme + worldLimits // Create another choropleth by mapping the `GDP estimate` variable to the `fill` aesthetic. letsPlot() + geomMap(data = world, color = "white") { fill = "gdp_md_est" } + ggsize(800, 400) + voidTheme + worldLimits // Average temperatures val climateData = mapOf( "region" to listOf("Europe", "Asia", "North America", "Africa", "Australia", "Oceania"), "avg_temp" to listOf(8.6, 16.6, 11.7, 21.9, 14.9, 23.9) ) // Join `data` and `map` using the `mapJoin` parameter. // For the sake of the demo let's use `geom_rect` and customize the tooltip. letsPlot() + geomRect(data = climateData, map = world, mapJoin = "region" to "continent", color = "white", tooltips=layerTooltips().line("^fill C\u00b0")) { fill = "avg_temp" } + scaleFillGradient(low = "light_blue", high = "dark_green", name="Average t[C\u00b0]") + ggsize(800, 400) + voidTheme