Skip to content

Commit

Permalink
Add the "annotation" and "Hurricane Katrina" examples from Cartopy
Browse files Browse the repository at this point in the history
More to come soon
  • Loading branch information
asinghvi17 committed Jun 8, 2024
1 parent 702eb97 commit 2794b3e
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 2 deletions.
6 changes: 4 additions & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ examples = [
"italy.jl",
"histogram.jl",
"contours.jl",
"world_population.jl",
"graph_on_usa.jl",
"orthographic.jl",
"german_lakes.jl",
"geostationary_image.jl",
"multiple_crs.jl",
joinpath("gmt", "antioquia.jl"),
"world_population.jl",
joinpath("cartopy", "annotation.jl"),
joinpath("cartopy", "katrina.jl"),
"german_lakes.jl",
"field_and_countries.jl",
"meshimage.jl",
"projections.jl",
Expand Down
34 changes: 34 additions & 0 deletions examples/cartopy/annotation.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# # Annotated plot
# This example is translated from [this Cartopy example](https://scitools.org.uk/cartopy/docs/latest/gallery/lines_and_polygons/feature_creation.html#sphx-glr-gallery-lines-and-polygons-feature-creation-py).

using CairoMakie, GeoMakie, Makie
using Makie: GeometryBasics
using NaturalEarth

states_fc = naturalearth("admin_1_states_provinces_lines", 50)


fig = Figure()
ga = GeoAxis(fig[1, 1]; limits = ((80, 170), (-45, 30)), dest = "+proj=longlat +datum=WGS84")
image!(ga, -180..180, -90..90, GeoMakie.earth() |> rotr90; interpolate = false)
poly!(ga, GeoMakie.land(); color = :lightyellow, strokecolor = :black, strokewidth = 1)
lines!(ga, GeoMakie.to_multilinestring.(states_fc.geometry); color = :gray)
fig
# Now to add the annotation:
const DATASOURCE = "Natural Earth"
const LICENSE = "public domain"
annotation_text = text!(
ga.scene, Point2f(0.05, 0.05); # plotting in relative coordinates - (0, 0) is bottom left, (1, 1) is top right
space = :relative, text = "© $DATASOURCE ($LICENSE)"
)
fig

_pad_rect(rect, padding::Real) = Rect(rect.origin .- padding, rect.widths .+ 2 * padding)
text_bbox = Makie.boundingbox(last(plots(ga.scene)))

annotation_box = poly!(ga.scene, _pad_rect(text_bbox, 4); space = :pixel, color = :white, strokecolor = :black, strokewidth = 2)
annotation_box.transformation.transform_func[] = identity
translate!(annotation_text, 0, 0, 110)
translate!(annotation_box, 0, 0, 109)
fig

71 changes: 71 additions & 0 deletions examples/cartopy/katrina.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# # Hurricane Katrina
# Taken from the [Cartopy `Hurricane Katrina` example](https://scitools.org.uk/cartopy/docs/latest/gallery/lines_and_polygons/hurricane_katrina.html#sphx-glr-gallery-lines-and-polygons-hurricane-katrina-py)

using CairoMakie, GeoMakie
using DataFrames
using NaturalEarth
import GeometryOps as GO
import LibGEOS # to activate buffering in GeometryOps

#=
The below data is a list of latitudes and a list of longitudes (lons, lats)
for Hurricane Katrina (2005).
The data was originally sourced from the HURDAT2 dataset from AOML/NOAA:
https://www.aoml.noaa.gov/hrd/hurdat/newhurdat-all.html on 14th Dec 2012.
=#
lons = [-75.1, -75.7, -76.2, -76.5, -76.9, -77.7, -78.4, -79.0,
-79.6, -80.1, -80.3, -81.3, -82.0, -82.6, -83.3, -84.0,
-84.7, -85.3, -85.9, -86.7, -87.7, -88.6, -89.2, -89.6,
-89.6, -89.6, -89.6, -89.6, -89.1, -88.6, -88.0, -87.0,
-85.3, -82.9]

lats = [23.1, 23.4, 23.8, 24.5, 25.4, 26.0, 26.1, 26.2, 26.2, 26.0,
25.9, 25.4, 25.1, 24.9, 24.6, 24.4, 24.4, 24.5, 24.8, 25.2,
25.7, 26.3, 27.2, 28.2, 29.3, 29.5, 30.2, 31.1, 32.6, 34.1,
35.6, 37.0, 38.6, 40.1]

katrina_path = GO.LineString(Point2d.(lons, lats))

# We can retrieve the US states from Natural Earth. This particular feature collection
# only contains US states.
states_df = DataFrame(naturalearth("admin_1_states_provinces_lakes", 110))
states_df.geometry .= GeoMakie.to_multipoly.(states_df.geometry)
states_df.color = fill(RGBAf(colorant"lightyellow"), size(states_df, 1))
# We also have to filter for the continental states only, since we're focused on those:
filter!(:name_en => !in(("Alaska", "Hawaii")), states_df)
# In order to get a sense of which states are indirectly affected, we intersect by a buffered version of the linestring!
# For context, let's see what this looks like:
buffered_katrina_path = LibGEOS.buffer(katrina_path, 2) # within 2 degrees of the path
affected_states = view(states_df, GO.intersects.(states_df.geometry, (buffered_katrina_path,)), :)
affected_states.color .= Makie.wong_colors()[end]
# Finally, we can intersect the states directly:
direct_states = view(states_df, GO.intersects.(states_df.geometry, (katrina_path,)), :)
direct_states.color .= Makie.wong_colors()[end-1]
# Now, we can plot these.
fig = Figure()
ga = GeoAxis(
fig[1, 1];
dest = "+proj=lcc +lon_0=-96 +lat_0=39 +lat_1=33 +lat_2=45"
)
hidedecorations!(ga)
poly!(ga, states_df.geometry; color = states_df.color, strokecolor = :black, strokewidth = 1.3)
fig
# We can also add the path for clarity:
lines!(ga, katrina_path; color = Makie.wong_colors()[1])
poly!(ga, buffered_katrina_path; color = Makie.wong_colors(0.2)[1])

fig
# Finally, we add a legend to the figure.
leg = axislegend(
ga,
[PolyElement(color = first(direct_states.color)), PolyElement(color = first(affected_states.color)), LineElement(color = Makie.wong_colors()[1]), PolyElement(color = Makie.wong_colors(0.2)[1])],
["Directly affected", "Indirectly affected", "Hurricane path", "2° away from path"],
position = :lb,
framevisible = false
)
ga.title = "Hurricane Katrina"
fig

0 comments on commit 2794b3e

Please sign in to comment.