Skip to content

Commit

Permalink
Add docstring + example + docs + changelog for #4744 (#4745)
Browse files Browse the repository at this point in the history
  • Loading branch information
briochemc authored Jan 20, 2025
1 parent 9c53e2f commit 47f089c
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [Unreleased]

- `contourf` (contour filled) now supports _curvilinear_ grids, where `x` and `y` are matrices (`contour` lines were added in v.0.22.0) [#4670](https://github.com/MakieOrg/Makie.jl/pull/4670).

## [0.22.1] - 2025-01-17

- Allow volume textures for mesh color, to e.g. implement a performant volume slice display [#2274](https://github.com/MakieOrg/Makie.jl/pull/2274).
Expand Down
22 changes: 22 additions & 0 deletions ReferenceTests/src/tests/examples2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,28 @@ end
fig
end

@reference_test "filled contour 2d with curvilinear grid" begin
x = -10:10
y = -10:10
# The curvilinear grid:
xs = [x + 0.01y^3 for x in x, y in y]
ys = [y + 10cos(x/40) for x in x, y in y]

# Now, for simplicity, we calculate the `Z` values to be
# the radius from the center of the grid (0, 10).
zs = sqrt.(xs .^ 2 .+ (ys .- 10) .^ 2)

# We can use Makie's tick finders to get some nice looking contour levels.
# This could also be Makie.get_tickvalues(Makie.LinearTicks(7), extrema(zs)...)
# but it's more stable as a test if we hardcode it.
levels = 0:4:20

# and now, we plot!
fig, ax, ctr = contourf(xs, ys, zs; levels = levels)

fig
end

@reference_test "contour labels 3D" begin
fig = Figure()
Axis3(fig[1, 1])
Expand Down
31 changes: 31 additions & 0 deletions docs/src/reference/plots/contourf.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,37 @@ contourf!(volcano, levels = 10)
f
```



### Curvilinear grids

`contourf` also supports _curvilinear_ grids, where `x` and `y` are both matrices of the same size as `z`.
This is similar to the input that [`surface`](@ref) accepts.

Let's warp a regular grid of `x` and `y` by some nonlinear function, and plot its contours:

```@figure
x = -10:10
y = -10:10
# The curvilinear grid:
xs = [x + 0.01y^3 for x in x, y in y]
ys = [y + 10cos(x/40) for x in x, y in y]
# Now, for simplicity, we calculate the `zs` values to be
# the radius from the center of the grid (0, 10).
zs = sqrt.(xs .^ 2 .+ (ys .- 10) .^ 2)
# We can use Makie's tick finders to get some nice looking contour levels:
levels = Makie.get_tickvalues(Makie.LinearTicks(7), extrema(zs)...)
# and now, we plot!
f = Figure()
ax1 = Axis(f[1, 1])
ctrf1 = contourf!(ax1, x, y, zs; levels = levels)
ax2 = Axis(f[1, 2])
ctrf2 = contourf!(ax2, xs, ys, zs; levels = levels)
f
```



## Attributes

```@attrdocs
Expand Down
16 changes: 10 additions & 6 deletions src/basic_recipes/contourf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
Plots a filled contour of the height information in `zs` at horizontal grid positions `xs`
and vertical grid positions `ys`.
`xs` and `ys` can be vectors for rectilinear grids
or matrices for curvilinear grids,
similar to how [`surface`](@ref) works.
"""
@recipe Contourf begin
"""
Expand All @@ -20,7 +24,7 @@ and vertical grid positions `ys`.
Determines how the `levels` attribute is interpreted, either `:normal` or `:relative`.
In `:normal` mode, the levels correspond directly to the z values.
In `:relative` mode, you specify edges by the fraction between minimum and maximum value of `zs`.
This can be used for example to draw bands for the upper 90% while excluding the lower 10% with `levels = 0.1:0.1:1.0, mode = :relative`.
This can be used for example to draw bands for the upper 90% while excluding the lower 10% with `levels = 0.1:0.1:1.0, mode = :relative`.
"""
mode = :normal
colormap = @inherit colormap
Expand Down Expand Up @@ -79,8 +83,8 @@ This is an internal function, not public API and should not be treated as such.
uses Isoband.jl internally.
"""
function calculate_contourf_polys!(
polys::AbstractVector{<:GeometryBasics.Polygon}, colors::AbstractVector,
xs::AbstractVector, ys::AbstractVector, zs::AbstractMatrix,
polys::AbstractVector{<:GeometryBasics.Polygon}, colors::AbstractVector,
xs::AbstractVector, ys::AbstractVector, zs::AbstractMatrix,
lows::AbstractVector, highs::AbstractVector
)
empty!(polys)
Expand Down Expand Up @@ -110,8 +114,8 @@ end
# Here, we simply use a linear interpolation to transform the points before storing them.

function calculate_contourf_polys!(
polys::AbstractVector{<:GeometryBasics.Polygon}, colors::AbstractVector,
xs::AbstractMatrix, ys::AbstractMatrix, zs::AbstractMatrix,
polys::AbstractVector{<:GeometryBasics.Polygon}, colors::AbstractVector,
xs::AbstractMatrix, ys::AbstractMatrix, zs::AbstractMatrix,
lows::AbstractVector, highs::AbstractVector
)
empty!(polys)
Expand Down Expand Up @@ -141,7 +145,7 @@ function calculate_contourf_polys!(
points = Point2f.(group.x, group.y)
polygroups = _group_polys(points, group.id)
for rectilinear_polygroup in polygroups
# NOTE: This is the only major change between the two versions
# NOTE: This is the only major change between the two versions
# of the function `calculate_contourf_polys!`.
# we reproject the lines to curvilinear space
polygroup = map(rectilinear_polygroup) do ring
Expand Down

0 comments on commit 47f089c

Please sign in to comment.