Generalize GR tick label rotations (#3782)
* gr tick rotations * consistency * start of angle offset work * Working! * simplify logic * gr tick rotations * consistency * start of angle offset work * Working! * simplify logic * all offsets * Rebase * tick factor reversion * Fix for 3d plots * simplification * offset update * bump offset * Remove conflict error * Resolve merge conflict error. * Resolve merge conflict error * 3d done * remove excess * adjust offset * restore offset * fix sign check Co-authored-by: t-bltg <tf.bltg@gmail.com> Co-authored-by: Simon Christ <SimonChrist@gmx.de>
This commit is contained in:
parent
9d56e72f6a
commit
aca2aa49b8
@ -671,31 +671,19 @@ end
|
|||||||
|
|
||||||
function gr_set_tickfont(sp, letter)
|
function gr_set_tickfont(sp, letter)
|
||||||
axis = sp[get_attr_symbol(letter, :axis)]
|
axis = sp[get_attr_symbol(letter, :axis)]
|
||||||
|
|
||||||
# invalidate alignment changes for small rotations (|θ| < 45°)
|
|
||||||
trigger(rot) = abs(sind(rot)) < abs(cosd(rot)) ? 0 : sign(rot)
|
|
||||||
|
|
||||||
rot = axis[:rotation]
|
|
||||||
if letter === :x || (RecipesPipeline.is3d(sp) && letter === :y)
|
|
||||||
halign = (:left, :hcenter, :right)[trigger(rot) + 2]
|
|
||||||
valign = (axis[:mirror] ? :bottom : :top, :vcenter)[trigger(abs(rot)) + 1]
|
|
||||||
else
|
|
||||||
halign = (axis[:mirror] ? :left : :right, :hcenter)[trigger(abs(rot)) + 1]
|
|
||||||
valign = (:top, :vcenter, :bottom)[trigger(rot) + 2]
|
|
||||||
end
|
|
||||||
gr_set_font(
|
gr_set_font(
|
||||||
tickfont(axis),
|
tickfont(axis),
|
||||||
sp,
|
sp,
|
||||||
halign = halign,
|
|
||||||
valign = valign,
|
|
||||||
rotation = axis[:rotation],
|
rotation = axis[:rotation],
|
||||||
color = axis[:tickfontcolor],
|
color = axis[:tickfontcolor],
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# size of the text with no rotation
|
||||||
function gr_text_size(str)
|
function gr_text_size(str)
|
||||||
GR.savestate()
|
GR.savestate()
|
||||||
GR.selntran(0)
|
GR.selntran(0)
|
||||||
|
GR.setcharup(0, 1)
|
||||||
xs, ys = gr_inqtext(0, 0, string(str))
|
xs, ys = gr_inqtext(0, 0, string(str))
|
||||||
l, r = extrema(xs)
|
l, r = extrema(xs)
|
||||||
b, t = extrema(ys)
|
b, t = extrema(ys)
|
||||||
@ -705,9 +693,11 @@ function gr_text_size(str)
|
|||||||
return w, h
|
return w, h
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# size of the text with rotation applied
|
||||||
function gr_text_size(str, rot)
|
function gr_text_size(str, rot)
|
||||||
GR.savestate()
|
GR.savestate()
|
||||||
GR.selntran(0)
|
GR.selntran(0)
|
||||||
|
GR.setcharup(0, 1)
|
||||||
xs, ys = gr_inqtext(0, 0, string(str))
|
xs, ys = gr_inqtext(0, 0, string(str))
|
||||||
l, r = extrema(xs)
|
l, r = extrema(xs)
|
||||||
b, t = extrema(ys)
|
b, t = extrema(ys)
|
||||||
@ -720,6 +710,15 @@ end
|
|||||||
text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h
|
text_box_width(w, h, rot) = abs(cosd(rot)) * w + abs(cosd(rot + 90)) * h
|
||||||
text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h
|
text_box_height(w, h, rot) = abs(sind(rot)) * w + abs(sind(rot + 90)) * h
|
||||||
|
|
||||||
|
function gr_get_3d_axis_angle(cvs, nt, ft, letter)
|
||||||
|
length(cvs) < 2 && return 0
|
||||||
|
tickpoints = [gr_w3tondc(sort_3d_axes(cv, nt, ft, letter)...) for cv ∈ cvs]
|
||||||
|
|
||||||
|
dx = tickpoints[2][1] - tickpoints[1][1]
|
||||||
|
dy = tickpoints[2][2] - tickpoints[1][2]
|
||||||
|
return atand(dy, dx)
|
||||||
|
end
|
||||||
|
|
||||||
function gr_get_ticks_size(ticks, rot)
|
function gr_get_ticks_size(ticks, rot)
|
||||||
w, h = 0.0, 0.0
|
w, h = 0.0, 0.0
|
||||||
for (cv, dv) in zip(ticks...)
|
for (cv, dv) in zip(ticks...)
|
||||||
@ -1560,13 +1559,35 @@ function gr_label_ticks(sp, letter, ticks)
|
|||||||
oamin, oamax = axis_limits(sp, oletter)
|
oamin, oamax = axis_limits(sp, oletter)
|
||||||
gr_set_tickfont(sp, letter)
|
gr_set_tickfont(sp, letter)
|
||||||
out_factor = ifelse(axis[:tick_direction] === :out, 1.5, 1)
|
out_factor = ifelse(axis[:tick_direction] === :out, 1.5, 1)
|
||||||
x_offset = isy ? -1.5e-2 * out_factor : 0
|
x_base_offset = isy ? -1.5e-2 * out_factor : 0
|
||||||
y_offset = isy ? 0 : -8e-3 * out_factor
|
y_base_offset = isy ? 0 : -8e-3 * out_factor
|
||||||
|
|
||||||
|
rot = axis[:rotation] % 360
|
||||||
ov = sp[:framestyle] == :origin ? 0 : xor(oaxis[:flip], axis[:mirror]) ? oamax : oamin
|
ov = sp[:framestyle] == :origin ? 0 : xor(oaxis[:flip], axis[:mirror]) ? oamax : oamin
|
||||||
sgn = axis[:mirror] ? -1 : 1
|
sgn = axis[:mirror] ? -1 : 1
|
||||||
|
sgn2 = iseven(Int(floor(rot / 90))) ? -1 : 1
|
||||||
|
sgn3 = if isy
|
||||||
|
-360 < rot < -180 || 0 < rot < 180 ? 1 : -1
|
||||||
|
else
|
||||||
|
rot < -270 || -90 < rot < 90 || rot > 270 ? 1 : -1
|
||||||
|
end
|
||||||
for (cv, dv) in zip(ticks...)
|
for (cv, dv) in zip(ticks...)
|
||||||
x, y = GR.wctondc(reverse_if((cv, ov), isy)...)
|
x, y = GR.wctondc(reverse_if((cv, ov), isy)...)
|
||||||
|
sz_rot = gr_text_size(dv, rot)
|
||||||
|
sz = gr_text_size(dv)
|
||||||
|
x_offset = x_base_offset
|
||||||
|
y_offset = y_base_offset
|
||||||
|
if isy
|
||||||
|
x_offset += -first(sz_rot) / 2
|
||||||
|
if rot % 90 != 0
|
||||||
|
y_offset += sgn2 * last(sz_rot) / 2 + sgn3 * last(sz) * cosd(rot) / 2
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if rot % 90 != 0
|
||||||
|
x_offset += sgn2 * first(sz_rot) / 2 + sgn3 * last(sz) * sind(rot) / 2
|
||||||
|
end
|
||||||
|
y_offset += -last(sz_rot) / 2
|
||||||
|
end
|
||||||
gr_text(x + sgn * x_offset, y + sgn * y_offset, dv)
|
gr_text(x + sgn * x_offset, y + sgn * y_offset, dv)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1577,6 +1598,9 @@ function gr_label_ticks_3d(sp, letter, ticks)
|
|||||||
near_letter = letter in (:x, :z) ? :y : :x
|
near_letter = letter in (:x, :z) ? :y : :x
|
||||||
far_letter = letter in (:x, :y) ? :z : :x
|
far_letter = letter in (:x, :y) ? :z : :x
|
||||||
|
|
||||||
|
isy = letter === :y
|
||||||
|
isz = letter === :z
|
||||||
|
|
||||||
ax = sp[get_attr_symbol(letter, :axis)]
|
ax = sp[get_attr_symbol(letter, :axis)]
|
||||||
nax = sp[get_attr_symbol(near_letter, :axis)]
|
nax = sp[get_attr_symbol(near_letter, :axis)]
|
||||||
fax = sp[get_attr_symbol(far_letter, :axis)]
|
fax = sp[get_attr_symbol(far_letter, :axis)]
|
||||||
@ -1584,7 +1608,7 @@ function gr_label_ticks_3d(sp, letter, ticks)
|
|||||||
amin, amax = axis_limits(sp, letter)
|
amin, amax = axis_limits(sp, letter)
|
||||||
namin, namax = axis_limits(sp, near_letter)
|
namin, namax = axis_limits(sp, near_letter)
|
||||||
famin, famax = axis_limits(sp, far_letter)
|
famin, famax = axis_limits(sp, far_letter)
|
||||||
n0, n1 = letter === :y ? (namax, namin) : (namin, namax)
|
n0, n1 = isy ? (namax, namin) : (namin, namax)
|
||||||
|
|
||||||
# find out which axes we are dealing with
|
# find out which axes we are dealing with
|
||||||
i = findfirst(==(letter), (:x, :y, :z))
|
i = findfirst(==(letter), (:x, :y, :z))
|
||||||
@ -1601,27 +1625,52 @@ function gr_label_ticks_3d(sp, letter, ticks)
|
|||||||
nt = sp[:framestyle] == :origin ? 0 : ax[:mirror] ? n1 : n0
|
nt = sp[:framestyle] == :origin ? 0 : ax[:mirror] ? n1 : n0
|
||||||
ft = sp[:framestyle] == :origin ? 0 : ax[:mirror] ? famax : famin
|
ft = sp[:framestyle] == :origin ? 0 : ax[:mirror] ? famax : famin
|
||||||
|
|
||||||
xoffset = if letter === :x
|
rot = mod(ax[:rotation], 360)
|
||||||
(sp[:yaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:xaxis][:tick_direction] == :out ? 1.5 : 1)
|
sgn = ax[:mirror] ? -1 : 1
|
||||||
elseif letter === :y
|
|
||||||
(sp[:yaxis][:mirror] ? -1 : 1) * 1e-2 * (sp[:yaxis][:tick_direction] == :out ? 1.5 : 1)
|
|
||||||
else
|
|
||||||
(sp[:zaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:zaxis][:tick_direction] == :out ? 1.5 : 1)
|
|
||||||
end
|
|
||||||
yoffset = if letter === :x
|
|
||||||
(sp[:xaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:xaxis][:tick_direction] == :out ? 1.5 : 1)
|
|
||||||
elseif letter === :y
|
|
||||||
(sp[:yaxis][:mirror] ? 1 : -1) * 1e-2 * (sp[:yaxis][:tick_direction] == :out ? 1.5 : 1)
|
|
||||||
else
|
|
||||||
0
|
|
||||||
end
|
|
||||||
|
|
||||||
cvs, dvs = ticks
|
cvs, dvs = ticks
|
||||||
ax[:flip] && reverse!(cvs)
|
ax[:flip] && reverse!(cvs)
|
||||||
|
|
||||||
|
axisθ = isz ? 270 : mod(gr_get_3d_axis_angle(cvs, nt, ft, letter), 360) # issue: doesn't work with 1 tick
|
||||||
|
axisϕ = mod(axisθ - 90, 360)
|
||||||
|
|
||||||
|
out_factor = ifelse(ax[:tick_direction] === :out, 1.5, 1)
|
||||||
|
axisoffset = out_factor * 1.2e-2
|
||||||
|
x_base_offset = axisoffset * cosd(axisϕ)
|
||||||
|
y_base_offset = axisoffset * sind(axisϕ)
|
||||||
|
|
||||||
|
sgn2a = sgn2b = sgn3 = 0
|
||||||
|
if axisθ != 0 || rot % 90 != 0
|
||||||
|
sgn2a = (axisθ != 90) &&
|
||||||
|
(axisθ == 0 && (rot < 90 || 180 ≤ rot < 270)) ||
|
||||||
|
(axisθ == 270) ||
|
||||||
|
(axisθ < 90 && (axisθ < rot < 90 || axisθ + 180 < rot < 270)) ||
|
||||||
|
(axisθ > 270 && (rot < 90 || axisθ - 180 < rot < 270 || rot > axisθ)) ? -1 : 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if (axisθ - 90) % 180 != 0 || (rot - 90) % 180 != 0
|
||||||
|
sgn2b = axisθ == 0 ||
|
||||||
|
(axisθ == 90 && (90 ≤ rot < 180 || 270 ≤ rot < 360)) ||
|
||||||
|
(axisθ == 270 && (rot < 90 || 180 ≤ rot < 270)) ||
|
||||||
|
(axisθ < 90 && (axisθ < rot < 180 || axisθ + 180 < rot)) ||
|
||||||
|
(axisθ > 270 && (rot < axisθ - 180 || 180 ≤ rot < axisθ)) ? -1 : 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if !(axisθ == 0 && rot % 180 == 0) && ((rot - 90) % 180 != 0)
|
||||||
|
sgn3 = (axisθ == 0 && 90 < rot < 270) ||
|
||||||
|
(axisθ == 90 && rot < 180) ||
|
||||||
|
(axisθ == 270 && rot > 180) ||
|
||||||
|
(axisθ < 90 && (rot < axisθ || 90 ≤ rot < 180 || axisθ + 180 < rot < 270)) ||
|
||||||
|
(axisθ > 270 && (90 ≤ rot < axisθ - 180 || 180 ≤ rot < 270 || rot > axisθ)) ? -1 : 1
|
||||||
|
end
|
||||||
|
|
||||||
for (cv, dv) in zip((cvs, dvs)...)
|
for (cv, dv) in zip((cvs, dvs)...)
|
||||||
xi, yi = gr_w3tondc(sort_3d_axes(cv, nt, ft, letter)...)
|
xi, yi = gr_w3tondc(sort_3d_axes(cv, nt, ft, letter)...)
|
||||||
gr_text(xi + xoffset, yi + yoffset, dv)
|
sz_rot = gr_text_size(dv, rot)
|
||||||
|
sz = gr_text_size(dv)
|
||||||
|
x_offset = x_base_offset + sgn2a * first(sz_rot) / 2 + sgn3 * last(sz) * sind(rot) / 2
|
||||||
|
y_offset = y_base_offset + sgn2b * last(sz_rot) / 2 + sgn3 * last(sz) * cosd(rot) / 2
|
||||||
|
gr_text(xi + sgn * x_offset, yi + sgn * y_offset, dv)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2084,3 +2133,4 @@ function _display(plt::Plot{GRBackend})
|
|||||||
end
|
end
|
||||||
|
|
||||||
closeall(::GRBackend) = GR.emergencyclosegks()
|
closeall(::GRBackend) = GR.emergencyclosegks()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user