Working with geometry objects

The SimpleSDMLayers package uses Points to represent coordinates, which allows to easily use GeometryBasics objects for masking. In this example, we will illustrate how we can get the values around a given point, and within a polygon. These functions all rely on mask to extract the values.

using SimpleSDMLayers
using GeometryBasics
using Plots
using JSON

layer = SimpleSDMPredictor(WorldClim, BioClim; resolution=5.0, left=-89., right=-70., top=27., bottom=15.)
SDM predictor → 144×228 grid with 5822 Float32-valued cells
  Latitudes	15.0 ⇢ 27.0
  Longitudes	-89.0 ⇢ -70.0

Let's have a look at the data, before applying any transformation:

plot(layer)

We will now define a center of 5 degree of radius centered on La Habana

la_habana = Point(-82.38304, 23.13302)
area = Circle(la_habana, 5.0)
GeometryBasics.Circle{Float64}([-82.38304, 23.13302], 5.0)

We can plot the background of the map, and add the clipped region:

plot(layer, c=:lightgrey, frame=:box)
plot!(mask(area, layer), c=:turku)
scatter!(la_habana, lab="", c=:white, msw=2.0)

This approach is useful if you want to mask according to a polygon. In this case, we will keep the values within a polygon representing Cuba. We grab data from Natural Earth Resources, that do not have the best resolution in terms of borders, but are sufficient for this illustration:

borders = download("https://raw.githubusercontent.com/AshKyd/geojson-regions/master/countries/50m/CUB.geojson")
cuba_data = JSON.parsefile(borders)
polys = cuba_data["geometry"]["coordinates"]
CUBA = SimpleSDMLayers._format_polygon.(polys)
7-element Vector{Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}}:
 Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}(GeometryBasics.Line{2, Float64}[Line([-82.56176757812503, 21.571679687500023] => [-82.65483398437496, 21.518652343749977]), Line([-82.65483398437496, 21.518652343749977] => [-82.85317382812497, 21.443896484375017]), Line([-82.85317382812497, 21.443896484375017] => [-82.95961914062498, 21.441308593750023]), Line([-82.95961914062498, 21.441308593750023] => [-83.06728515624995, 21.469384765624966]), Line([-83.06728515624995, 21.469384765624966] => [-83.14150390624998, 21.531884765624994]), Line([-83.14150390624998, 21.531884765624994] => [-83.1837890625, 21.59345703125004]), Line([-83.1837890625, 21.59345703125004] => [-83.18022460937497, 21.623046875000025]), Line([-83.18022460937497, 21.623046875000025] => [-83.11293945312497, 21.573681640624983]), Line([-83.11293945312497, 21.573681640624983] => [-83.05488281249993, 21.549414062500034]), Line([-83.05488281249993, 21.549414062500034] => [-83.0072265625, 21.56557617187502]), Line([-83.0072265625, 21.56557617187502] => [-82.97358398437498, 21.592285156250057]), Line([-82.97358398437498, 21.592285156250057] => [-83.08251953124997, 21.791406250000023]), Line([-83.08251953124997, 21.791406250000023] => [-83.07773437499998, 21.83349609375]), Line([-83.07773437499998, 21.83349609375] => [-82.99121093750003, 21.942724609375034]), Line([-82.99121093750003, 21.942724609375034] => [-82.75576171875002, 21.90952148437503]), Line([-82.75576171875002, 21.90952148437503] => [-82.71455078124998, 21.890283203125023]), Line([-82.71455078124998, 21.890283203125023] => [-82.68183593749995, 21.821142578125063]), Line([-82.68183593749995, 21.821142578125063] => [-82.62939453125001, 21.766894531250017]), Line([-82.62939453125001, 21.766894531250017] => [-82.56782226562501, 21.62182617187503]), Line([-82.56782226562501, 21.62182617187503] => [-82.56176757812503, 21.571679687500023])], GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}[])
 Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}(GeometryBasics.Line{2, Float64}[Line([-77.66899414062493, 21.951953125000045] => [-77.71005859374995, 21.92133789062504]), Line([-77.71005859374995, 21.92133789062504] => [-77.75502929687497, 21.965576171875]), Line([-77.75502929687497, 21.965576171875] => [-77.78364257812495, 21.970410156249983]), Line([-77.78364257812495, 21.970410156249983] => [-77.82319335937501, 21.987939453125023]), Line([-77.82319335937501, 21.987939453125023] => [-77.9, 22.037158203125014]), Line([-77.9, 22.037158203125014] => [-77.91855468749998, 22.088085937499983]), Line([-77.91855468749998, 22.088085937499983] => [-77.85473632812494, 22.091943359374966]), Line([-77.85473632812494, 22.091943359374966] => [-77.77441406250003, 22.08295898437501]), Line([-77.77441406250003, 22.08295898437501] => [-77.63369140624994, 22.054003906250074]), Line([-77.63369140624994, 22.054003906250074] => [-77.64599609374997, 21.996484374999966]), Line([-77.64599609374997, 21.996484374999966] => [-77.66899414062493, 21.951953125000045])], GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}[])
 Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}(GeometryBasics.Line{2, Float64}[Line([-77.87939453125, 22.127539062500034] => [-77.91235351562497, 22.124707031249983]), Line([-77.91235351562497, 22.124707031249983] => [-78.01191406249998, 22.16640625000005]), Line([-78.01191406249998, 22.16640625000005] => [-78.04165039062502, 22.20126953125003]), Line([-78.04165039062502, 22.20126953125003] => [-78.006689453125, 22.24799804687498]), Line([-78.006689453125, 22.24799804687498] => [-77.99921874999998, 22.298730468749994]), Line([-77.99921874999998, 22.298730468749994] => [-77.98564453124996, 22.302099609374977]), Line([-77.98564453124996, 22.302099609374977] => [-77.96958007812498, 22.240673828124983]), Line([-77.96958007812498, 22.240673828124983] => [-77.89365234374996, 22.214550781249983]), Line([-77.89365234374996, 22.214550781249983] => [-77.88911132812491, 22.201074218749994]), Line([-77.88911132812491, 22.201074218749994] => [-77.84248046874993, 22.148974609375045]), Line([-77.84248046874993, 22.148974609375045] => [-77.87939453125, 22.127539062500034])], GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}[])
 Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}(GeometryBasics.Line{2, Float64}[Line([-78.02709960937497, 22.28515625] => [-78.04750976562497, 22.268505859374983]), Line([-78.04750976562497, 22.268505859374983] => [-78.10166015624998, 22.305761718750006]), Line([-78.10166015624998, 22.305761718750006] => [-78.18002929687495, 22.321972656250036]), Line([-78.18002929687495, 22.321972656250036] => [-78.22612304687493, 22.379980468750034]), Line([-78.22612304687493, 22.379980468750034] => [-78.27001953125, 22.40224609375005]), Line([-78.27001953125, 22.40224609375005] => [-78.27353515625, 22.42358398437503]), Line([-78.27353515625, 22.42358398437503] => [-78.20097656249996, 22.437646484374962]), Line([-78.20097656249996, 22.437646484374962] => [-78.15058593750001, 22.43149414062506]), Line([-78.15058593750001, 22.43149414062506] => [-78.09414062499997, 22.38720703125]), Line([-78.09414062499997, 22.38720703125] => [-78.061669921875, 22.305908203125057]), Line([-78.061669921875, 22.305908203125057] => [-78.02709960937497, 22.28515625])], GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}[])
 Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}(GeometryBasics.Line{2, Float64}[Line([-78.63012695312499, 22.552246093750057] => [-78.49287109375001, 22.53105468749999]), Line([-78.49287109375001, 22.53105468749999] => [-78.4453125, 22.54375]), Line([-78.4453125, 22.54375] => [-78.39956054687502, 22.547460937500063]), Line([-78.39956054687502, 22.547460937500063] => [-78.35122070312501, 22.538623046875017]), Line([-78.35122070312501, 22.538623046875017] => [-78.28388671874998, 22.45546875000005]), Line([-78.28388671874998, 22.45546875000005] => [-78.34301757812493, 22.445117187500074]), Line([-78.34301757812493, 22.445117187500074] => [-78.38994140625, 22.445117187500074]), Line([-78.38994140625, 22.445117187500074] => [-78.42456054687494, 22.460107421875023]), Line([-78.42456054687494, 22.460107421875023] => [-78.54765624999997, 22.464013671875023]), Line([-78.54765624999997, 22.464013671875023] => [-78.62900390625003, 22.488183593749966]), Line([-78.62900390625003, 22.488183593749966] => [-78.67363281249999, 22.50883789062499]), Line([-78.67363281249999, 22.50883789062499] => [-78.69550781249998, 22.533984375000045]), Line([-78.69550781249998, 22.533984375000045] => [-78.63012695312499, 22.552246093750057])], GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}[])
 Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}(GeometryBasics.Line{2, Float64}[Line([-79.34956054687493, 22.663916015625063] => [-79.34790039062493, 22.637695312500057]), Line([-79.34790039062493, 22.637695312500057] => [-79.52275390624995, 22.711132812500008]), Line([-79.52275390624995, 22.711132812500008] => [-79.59785156249998, 22.787646484375045]), Line([-79.59785156249998, 22.787646484375045] => [-79.62817382812501, 22.80522460937507]), Line([-79.62817382812501, 22.80522460937507] => [-79.57915039062499, 22.806738281250034]), Line([-79.57915039062499, 22.806738281250034] => [-79.382177734375, 22.681347656249983]), Line([-79.382177734375, 22.681347656249983] => [-79.34956054687493, 22.663916015625063])], GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}[])
 Polygon{2, Float64, GeometryBasics.Point2{Float64}, GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}, Vector{GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}}}(GeometryBasics.Line{2, Float64}[Line([-81.83745117187499, 23.16303710937495] => [-81.57543945312497, 23.11650390625007]), Line([-81.57543945312497, 23.11650390625007] => [-81.36362304687499, 23.129687500000017]), Line([-81.36362304687499, 23.129687500000017] => [-81.26235351562497, 23.156835937500034]), Line([-81.26235351562497, 23.156835937500034] => [-81.271630859375, 23.128613281249955]), Line([-81.271630859375, 23.128613281249955] => [-81.17861328124997, 23.059667968750034]), Line([-81.17861328124997, 23.059667968750034] => [-81.14462890624998, 23.054931640625053]), Line([-81.14462890624998, 23.054931640625053] => [-81.00766601562495, 23.089843749999968]), Line([-81.00766601562495, 23.089843749999968] => [-80.65014648437493, 23.10307617187499]), Line([-80.65014648437493, 23.10307617187499] => [-80.61342773437502, 23.08374023437497]), Line([-80.61342773437502, 23.08374023437497] => [-80.55048828124998, 23.01660156249997])  …  Line([-84.36127929687498, 22.37890625] => [-84.28134765624993, 22.474218750000063]), Line([-84.28134765624993, 22.474218750000063] => [-84.12177734374995, 22.618554687499962]), Line([-84.12177734374995, 22.618554687499962] => [-84.04492187500003, 22.666015625000057]), Line([-84.04492187500003, 22.666015625000057] => [-83.25781249999997, 22.967578125000017]), Line([-83.25781249999997, 22.967578125000017] => [-83.17724609375, 22.983007812500063]), Line([-83.17724609375, 22.983007812500063] => [-82.66582031249997, 23.043554687500034]), Line([-82.66582031249997, 23.043554687500034] => [-82.58779296875, 23.064550781250063]), Line([-82.58779296875, 23.064550781250063] => [-82.35053710937498, 23.153955078124962]), Line([-82.35053710937498, 23.153955078124962] => [-82.10136718750002, 23.190429687500025]), Line([-82.10136718750002, 23.190429687500025] => [-81.83745117187499, 23.16303710937495])], GeometryBasics.LineString{2, Float64, GeometryBasics.Point2{Float64}, Base.ReinterpretArray{GeometryBasics.Line{2, Float64}, 1, Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, GeometryBasics.TupleView{Tuple{GeometryBasics.Point2{Float64}, GeometryBasics.Point2{Float64}}, 2, 1, Vector{GeometryBasics.Point2{Float64}}}, false}}[])

This object is actually a multi-polygon, or an array of polygons. The mask function can handle this:

plot(layer, c=:lightgrey, frame=:box)
plot!(mask(CUBA, layer), c=:turku)
scatter!(la_habana, lab="", c=:white, msw=2.0)

The delimitation of the area to crop is only as good as the underlying GeoJSON polygons, which in this case is missing some coastal areas. As a sidenote, the center of the grid cell is checked for being in the polygon (not any coordinate within the grid cell) - for this reason, coarser rasters (e.g. at 10 minutes resolution) may not respond perfectly well to masking in this way.