@@ -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
215216end
241242# ---------------------------------------------------------------------------------------------------
242243contourf! (cmd0:: String = " " , arg1= nothing , arg2= nothing ; kw... ) = contourf (cmd0, arg1, arg2; first= false , kw... )
243244contourf (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
0 commit comments