Skip to content

Commit 79d24b0

Browse files
authored
Add an option to contourf to plot Tanaka contours. (#1840)
* Add an option to contourf to plot Tanaka contours. * Don't plot the title twice.
1 parent be57a03 commit 79d24b0

4 files changed

Lines changed: 42 additions & 6 deletions

File tree

src/common_options.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2332,6 +2332,8 @@ function add_opt(d::Dict, cmd::String, opt::String, symbs::VMs, mapa; grow_mat=n
23322332
cmd = add_opt(d, cmd, opt, mapa)
23332333
end
23342334
return cmd
2335+
elseif (val == true || val === "") # Just the flag
2336+
return string(cmd, " -", opt)
23352337
elseif (expand_str && isa(mapa, NamedTuple)) # Use the mapa KEYS as possibe values of 'val'
23362338
cmd_ = ""
23372339
for k in keys(mapa)

src/contourf.jl

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ function contourf(cmd0::String, arg1, arg2, first::Bool, d::Dict{Symbol,Any})
9797

9898
dict_auto_add!(d) # The ternary module may send options via another channel
9999
CPT_arg::GMTcpt = (isa(arg1, GMTcpt)) ? arg1 : (isa(arg2, GMTcpt) ? arg2 : GMTcpt()) # Fish a CPT, if any.
100+
do_tanaka = ((val = find_in_dict(d, [:tanaka])[1]) !== nothing)
101+
do_tanaka && (azim::Float64 = Float64(val); (azim == 1.0) && (azim = 315)) # To allow also tanaka = 1
100102

101103
CPT::GMTcpt = GMTcpt(); C_contours = ""; C_int = 0;
102104
if ((val = find_in_dict(d, [:C :cont :contour :contours :levels])[1]) !== nothing)
@@ -194,8 +196,7 @@ function contourf(cmd0::String, arg1, arg2, first::Bool, d::Dict{Symbol,Any})
194196
if (opt_T !== nothing) d[:T] = opt_T end
195197
if (opt_S !== nothing) d[:S] = opt_S end
196198
if (opt_W !== nothing) d[:W] = opt_W end
197-
#grdcontour(cmd0, arg1; first=false, d...)
198-
grdcontour_helper(cmd0, arg1; first=false, d...)
199+
do_tanaka ? tanakacontour(arg1, d, azim) : grdcontour_helper(cmd0, arg1; first=false, d...)
199200
else
200201
if (!isempty(CPT_arg))
201202
d[:C] = CPT_arg;
@@ -209,7 +210,7 @@ function contourf(cmd0::String, arg1, arg2, first::Bool, d::Dict{Symbol,Any})
209210
d[:I] = true
210211
(C_int != 0 && opt_W === nothing) && (opt_W = "0.25p")
211212
(opt_W !== nothing) && (d[:W] = opt_W)
212-
contour(arg1; first=first, d...)
213+
do_tanaka ? tanakacontour(arg1, d, azim) : contour(arg1; first=first, d...)
213214
end
214215

215216
end
@@ -241,4 +242,36 @@ end
241242
# ---------------------------------------------------------------------------------------------------
242243
contourf!(cmd0::String="", arg1=nothing, arg2=nothing; kw...) = contourf(cmd0, arg1, arg2; first=false, kw...)
243244
contourf(arg1, arg2=nothing; kw...) = contourf("", arg1, arg2, true, KW(kw))
244-
contourf!(arg1, arg2=nothing; kw...) = contourf("", arg1, arg2, false, KW(kw))
245+
contourf!(arg1, arg2=nothing; kw...) = contourf("", arg1, arg2, false, KW(kw))
246+
247+
# ---------------------------------------------------------------------------------------------------
248+
function tanakacontour(G, d, azim)
249+
# Tanaka contours are contour lines whose thickness and intensity vary based
250+
# on illumination direction, creating an illusion of 3D relief. Illuminated
251+
# slopes get lighter/thinner lines, shaded slopes get darker/thicker lines.
252+
253+
illum = grdgradient(G, azimuth=azim, norm="e0.5+a0.5") # Means result is in 0-1 range
254+
cont = append!(d[:C].range[:,1], d[:C].range[end]) # Contour levels from CPT
255+
C = grdcontour(G, cont=cont, dump=true)
256+
n_contours = length(C)
257+
delete!(d, [:C]); delete!(d, [:title]); # If passed, it was used already
258+
gray = makecpt(cmap=:gray, range=(-0.6,1.05))
259+
min_lw, diff_lw = 0.8, 0.7 # max_lw = min_lw + diff_lw, the thikest line width at the darkest sides
260+
261+
sampled = grdtrack(C, grid=illum) # Sample illumination values along this contour
262+
for contour = 1:n_contours # Process each contour segment
263+
# Draw contour segments with varying properties
264+
n_pts = size(C[contour].data, 1)
265+
lw = Vector{Float64}(undef, n_pts-1)
266+
for i in 1:n_pts-1
267+
# Average illumination for this contour
268+
C[contour].data[i, 3] = (sampled[contour][i, 4] + sampled[contour][i+1, 4]) * 0.5
269+
270+
# Line width: thicker in shadow, thinner in light
271+
lw[i] = min_lw + (1.0 - C[contour].data[i, 3]) * diff_lw
272+
end
273+
D = line2multiseg(C[contour].data, lt=lw, color=gray)
274+
(contour < n_contours) ? plot!(D) : plot!(D; d...) # Different call for last to include all options in 'd'
275+
end
276+
gmt_restart() # Something in GMT API is fck badly. Each repeated call takes longer, so limit the damages with this.
277+
end

src/utils_types.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ function line2multiseg(M::Matrix{T}; is3D::Bool=false, color::GMTcpt=GMTcpt(), a
11761176
_lt = (lt === nothing) ? Float64[] : vec(Float64.(lt))
11771177
if (!isempty(_lt))
11781178
nth = length(_lt)
1179-
if (nth < size(M,1))
1179+
if (nth < n_ds)
11801180
if (nth == 2) th::Vector{Float64} = collect(linspace(_lt[1], _lt[2], n_ds)) # If we have only 2 thicknesses.
11811181
else th = hlp_var_thk(lt, n_ds)
11821182
end
@@ -1219,7 +1219,7 @@ function hlp_var_thk(lt, n_ds)
12191219
# The cmd "vec(gmt_GMTdataset("sample1d -T -o1", [collect(1:nth) _lt], collect(linspace(1,nth,n_ds))).data)" causes
12201220
# function invalidation (Fck Julia) that goes up the stack chain. So we approx it with a 2nd order polynomial interp.
12211221
nth = length(lt)
1222-
p = polyfit(1:nth, lt)
1222+
p = polyfit(1:nth, lt, 2)
12231223
polyval(p, linspace(1, nth, n_ds))
12241224
end
12251225

test/test_B-GMTs.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
C = makecpt(range=(0,10,1));
3333
contourf(d, C, limits=(-0.5,9.5,0,5), pen=0.25, labels=(line=(:min,:max),), Vd=dbg2)
3434
contourf(d, C=C, limits=(-0.5,9.5,0,5), pen=0.25, labels=(line=(:min,:max),), Vd=dbg2)
35+
contourf(G, tanaka=true)
3536

3637
println(" EARTHTIDE")
3738
earthtide();

0 commit comments

Comments
 (0)